1.基本概念

1.1 概念

Opencv本质上是用于处理计算机视觉算法的一堆 C 和 C++源代码。

全称Open Source Computer Vision Library,即开放源代码的计算机视觉库。

高效性能的原因:

1.多线程支持:Opencv库中的某些操作可利用自动多核处理,通过并行处理提高性能。

2.硬件加速:OpenCV支持多种硬件加速技术,包括但不限于CUDA(NVIDIA的GPU编程模型)、OpenCL等,这些技术可以显著提升处理速度,特别是在执行大规模矩阵运算、卷积操作等任务时。

3.与硬件紧密集成:可直接访问硬件,如摄像头。

1.2 环境安装

pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simpl

2.基本操作

2.1 显示窗口

cv2.namedWindow为Opencv库中的一个函数,用于创建一个命名窗口,以便在该窗口显示图像和进行其他图像操作。

语法:

cv2.namedWindow(winname, flags=None)

参数说明:

  • winname(str):窗口名称,需唯一,以此识别窗口。

  • flags(int):窗口标致,用于设置窗口行为。默认值:cv2.WINDOW_AUTOSIZE

           常见标致:

              1.  cv2.WINDOW_AUTOSIZE:窗口大小根据图像自动调整。

               2. cv2.WINDOW_NORMAL:允许调整窗口大小。

案例:

import cv2

# 读取图像
image = cv2.imread('images/car.png')

# 创建一个名为 "Image Window" 的窗口,允许调整大小
cv2.namedWindow('Image Window', cv2.WINDOW_NORMAL)

#2 设置名字和窗口大小
cv2.resizeWindow("Image Window",500,300)


# 显示图像
cv2.imshow('Image Window', image)

# 等待用户按键

#使用 cv2.waitKey 暂停程序执行,等待用户按键。参数 0 表示无限期等待,直到有按键事件发生。
cv2.waitKey(0)

# 关闭所有窗口
cv2.destroyAllWindows()

2.2 创建空白图片

可使用np.zeros函数创建一个全零数组,表示为全黑的空白图像。数组形状需符合(height,width,3)

语法:

# 创建一个 500x500 像素的空白图像,3 个通道(RGB)
height, width, channels = 500, 500, 3
blank_image = np.zeros((height, width, channels), dtype=np.uint8)

np.uint8是NumPy库中定义的一种数据类型,表示无符号的8位整数,在常见的 RGB 图像中,每个颜色通道(红、绿、蓝)的强度值范围是从 0 到 255,这正好可以用 np.uint8 来表示

案例:

import cv2
import numpy as np

# 创建一个 500x500 像素的空白图像,3 个通道(RGB)
height, width, channels = 500, 500, 3
blank_image = np.zeros((height, width, channels), dtype=np.uint8)

# 显示空白图像
cv2.imshow('Image', blank_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

2.3 图像裁剪

假设你有一个图像 img,它的类型是 numpy.ndarrayimg[y:y+h, x:x+w] 的含义如下:

  • x: 子区域左上角的 x 坐标。

  • y: 子区域左上角的 y 坐标。

  • w: 子区域的宽度。

  • h: 子区域的高度。

切片操作

  • img[y:y+h, x:x+w] 提取的是从 (x, y) 开始,宽度为 w,高度为 h 的矩形区域。

案例:

image = cv2.imread("../images/car3.png")
x, y = 50, 60
w, h = 200, 650
width, height,c = image.shape

# 判断索引是否越界
if y+h < height and x+w < width:

    # 提取子区域
    img = image[y:y+h, x:x+w]

    # 显示原始图像和提取的子区域
    cv2.imshow('image',image)
    cv2.imshow('img',img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
else:
    print("索引越界")

2.4 调整图片大小

cv2.resize 是 OpenCV 库中的一个函数,用于调整图像的大小。这个函数在图像处理中非常常用,特别是在需要对图像进行缩放、放大或缩小以适应不同需求时。

案例:

import cv2

image = cv2.imread("../images/car3.png")

cv2.namedWindow('image', cv2.WINDOW_NORMAL)

#调整图片大小

cv2.resizeWindow('image', (400, 400))

cv2.imshow('image', image)

cv2.waitKey(0) cv2.destroyAllWindows()

#保存图片

cv2.imwritw("save_image/car3.png", image)

2.5 保存图片

cv2.imwrite 是 OpenCV 库中的一个函数,用于将图像保存到文件中。这个函数在图像处理和计算机视觉任务中非常常用,特别是在需要将处理后的图像结果保存到磁盘时。

语法:
cv2.imwrite(filename, img[, params])

参数说明

  • filename (str): 要保存的文件路径和名称。支持的文件格式包括 .jpg, .png, .bmp, .tiff 等。

  • img (numpy.ndarray): 要保存的图像。通常是一个二维或三维的 NumPy 数组,表示图像的像素值。

返回值

  • bool: 成功保存图像返回 True,否则返回 False

案例:

import cv2

# 读取图片
img = cv2.imread("images/car.png")


# 保存图片
rs = cv2.imwrite("save_image/car.png", img)
if rs:
    print("图像保存成功!")
else:
    print("图像保存失败!")

3.图像绘制

3.1 绘制直线

语法:

cv2.line(img, pt1, pt2, color, thickness lineType)

参数说明

  • img: 输出图像,即要在这张图上绘制直线的图像。通常是一个 NumPy 数组。

  • pt1: 直线的一个端点,是一个包含两个元素(x, y)的元组,代表该点的坐标。

  • pt2: 直线的另一个端点,也是一个包含两个元素(x, y)的元组,代表该点的坐标。

  • color: 直线的颜色,对于 BGR 图像,这应该是一个包含三个整数的元组,分别对应蓝色、绿色和红色的强度(例如 (255, 0, 0) 表示纯蓝色)。对于灰度图像,只需要一个整数值即可。

  • thickness: 可选参数,定义直线的宽度。默认值是 1

案例:

import cv2

image = cv2.imread("../images/car3.png")

#直线起点

start = (0, 0)

#直线终点

end = (110, 100)

cv2.line(image, start, end, (0,0,255), 2)

cv2.imshow('image',image)

cv2.waitKey(0)

cv2.destroyAllWindows()

3.2 绘制矩形

cv2.rectangle()函数用于在图像上绘制矩形。

该函数的语法如下:

 cv2.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]])

其中,参数解释如下:

  • img:要绘制矩形的图像。

  • pt1:矩形的一个顶点。

  • pt2:矩形对角线上的另一个顶点。

  • color:矩形的颜色,通常是一个表示BGR颜色的元组,例如(255, 0, 0)表示蓝色。

  • thickness:矩形边框的厚度,如果为负值或cv2.FILLED,表示填充整个矩形内部。

案例:

import cv2

image = cv2.imread("../images/car3.png")

#左上角顶点

start = (100, 100)

#右上角顶点

end = (200, 200)

#颜色为黄色

cv2.rectangle(image,start,end,(0,255,255),2)

cv2.imshow('image',image)

cv2.waitKey(0)

cv2.destroyAllWindows()

3.3 绘制圆形

案例:

import cv2

image = cv2.imread("../images/car3.png")

point = (200,200) radius = 100

cv2.circle(image,point,radius,(0,0,255),2)

cv2.imshow('image',image)

cv2.waitKey(0)

cv2.destroyAllWindows()

3.3 绘制文本

3.3.1 英文文本

cv2.putText 是 OpenCV 库中的一个函数,用于在图像上添加文本。这个函数在图像处理和计算机视觉任务中非常有用,特别是在需要标注图像、显示信息或调试时。

语法:

cv2.putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]])

参数说明

  • img (numpy.ndarray): 输入图像,通常是一个二维或三维的 NumPy 数组。

  • text (str): 要添加的文本字符串。

  • org (tuple): 文本的起始位置,是一个二元组 (x, y),表示文本左下角的坐标。

  • fontFace(int): 字体类型

  • fontScale (float): 字体大小的比例因子。

  • color (tuple): 文本颜色,是一个三元组 (B, G, R),表示蓝色、绿色和红色的值。

  • thickness (int, 可选): 文本线条的厚度,默认值为 1。

  • lineType

    (int, 可选): 线条类型,常见的线条类型包括:

    • cv2.LINE_4: 4 连通线

    • cv2.LINE_8: 8 连通线

    • cv2.LINE_AA: 抗锯齿线(默认值)

案例:

import cv2

image = cv2.imread("../images/car3.png")

# 定义文本内容

text = "hello world!"

# 设置文本字体类型

font = cv2.FONT_HERSHEY_SIMPLEX

# 在图像上绘制文本

cv2.putText(image,text,(100,100),font,1,(255,255,0),2,cv2.LINE_AA) cv2.imshow('image',image)

cv2.waitKey(0)

cv2.destroyAllWindows()

3.3.2 中文文本

在使用 OpenCV 的 cv2.putText 函数添加中文时,可能会遇到显示乱码的问题。这是因为 OpenCV 默认使用的字体不支持中文字符。为了在图像上正确显示中文,可以使用 PIL(Pillow)库来处理文本,然后将文本渲染到图像上

1.确保你已经安装了 opencv-pythonPillow 库。如果没有安装,可以通过 pip 安装:

pip install opencv-python pillow -i https://pypi.tuna.tsinghua.edu.cn/simple

2.下载一个中文字体文件,常见的中文字体文件有 simhei.ttfsimsun.ttc 等。你可以从系统中找到这些字体文件,或者从互联网下载。

3. 定义put_text函数

import cv2
import numpy as np
from PIL import Image,ImageDraw,ImageFont

def put_text(image, text, position, font_path, font_size, color):
    # 将 OpenCV 图像转换为 PIL 图像
    pil_image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
    
    # 创建一个可以在给定图像上绘图的对象
    draw = ImageDraw.Draw(pil_image)
    
    # 加载字体
    font = ImageFont.truetype(font_path, font_size)
    
    # 在图像上绘制文本
    draw.text(position, text, fill=color, font=font)
    
    # 将 PIL 图像转换回 OpenCV 图像
    image_with_text = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
    
    return image_with_text

案例:

# 读取图像

image = cv2.imread("../images/car3.png")

# 定义文本内容

text = "你好,世界!"

#文本开始位置

position = (100,100)

# 字体路径

font_path ="../myfont/simsun.ttc"

# 字体大小

font_size = 20

# 字体颜色

color = (255,0,255)

# 在图像上添加中文文本

image_text = put_text(image, text, position, font_path, font_size, color)

# 显示图像

cv2.imshow('image',image_text)

cv2.waitKey(0)

cv2.destroyAllWindows()

4.鼠标控制

cv2.setMouseCallback 是 OpenCV 提供的一个非常有用的函数,它允许用户定义一个回调函数,当鼠标事件发生时(如点击、释放、移动等),该回调函数会被调用。这在创建交互式应用程序时特别有用,比如图像标注工具、绘图程序等。

案例:

import cv2

# 创建鼠标回调函数

def draw_test(event,x,y,flags,param):

         print(x,y)

image = cv2.imread("../images/car3.png")

cv2.namedWindow("image")

# 设置鼠标回调函数

cv2.setMouseCallback("image",draw_test)

cv2.imshow("image",image)

cv2.waitKey(0)

cv2.destroyAllWindows()

  1. draw_test函数:

    • event: 鼠标事件类型,如 cv2.EVENT_LBUTTONDOWN 表示左键按下。

    • x, y: 鼠标事件发生时的坐标。

    • flags: 额外的标志位,通常不用。

    • param: 传递给回调函数的参数,通常不用。

cv2.setMouseCallback('image', draw_test) 设置鼠标回调函数,当在 'image' 窗口中发生鼠标事件时,调用 draw_test 函数

在图像上绘制圆形:

import cv2

def draw_circle(event, x, y, flags, param):

        if event == cv2.EVENT_LBUTTONDOWN:

                cv2.circle(image, (x, y), 15, (0, 0, 255), 5)

        elif event == cv2.EVENT_LBUTTONUP:

                 print("鼠标按下松开")

         elif event == cv2.EVENT_MOUSEMOVE:

                 print("鼠标移动了")

image = cv2.imread("../images/car3.png")

# 创建窗口

cv2.namedWindow("image")

cv2.setMouseCallback("image",draw_circle)

#永真循环,图像被绘制后显示图片,直到按下ESC键退出

while True: cv2.imshow('image', image)

         if cv2.waitKey(1) == 27:

                 break

cv2.destroyAllWindows()

画直线:

import cv2

# 设置一个全局变量,记录是否开始画画
drawing = False
# 记录移动的坐标
points = []
end = 0
def draw_line(event, x, y, flags, param):
    global drawing, points,i
    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        # points.append((x, y))

    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False

    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing:
            # 记录所有坐标
            points.append((x, y))
            for i in range(len(points)):
                start = points[i]
                if i+1 < len(points):
                    end = points[i+1]
                cv2.line(image,start,end,(0,0,255),2)

image = cv2.imread("../images/car3.png")
cv2.namedWindow("image")
cv2.setMouseCallback("image",draw_line)

while True:
        cv2.imshow('image', image)
        if cv2.waitKey(1) == 27:
            break
cv2.destroyAllWindows()

5.视频处理

cv2.VideoCapture 是 OpenCV 库中的一个类,用于从摄像头或视频文件中捕获视频帧。这个类提供了多种方法来控制视频捕获的过程,包括打开视频文件、读取视频帧、获取视频属性等。

常用方法

  1. read()

read() 方法用于从视频源中读取下一帧。它返回一个布尔值和图像帧。布尔值表示是否成功读取了帧,图像帧是一个 NumPy 数组。

ret, frame = cap.read()
if not ret:
    print("Failed to grab frame")
    break

2.release()

release() 方法用于释放视频捕获资源。在完成视频处理后,必须调用此方法来释放摄像头或视频文件.

3.isOpened()

isOpened() 方法用于检查视频捕获对象是否已经成功打开。

4.get()set()

get()set() 方法用于获取和设置视频捕获属性。常用的属性包括帧宽、帧高、帧率等。

# 获取帧宽
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)

# 获取帧高
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)

# 获取帧率
fps = cap.get(cv2.CAP_PROP_FPS)

# 设置帧宽
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)

# 设置帧高
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

案例:

import cv2

video = cv2.VideoCapture("../video/1.mp4")
if not video.isOpened():
    print("视频未打开")
    exit()

# 获取视频帧率
fps = video.get(cv2.CAP_PROP_FPS)
# 计算桢间延迟,播放速度
delay = int(1000 / fps)
h = video.get(cv2.CAP_PROP_FRAME_HEIGHT)
print("桢高:",h)
while True:
    # ret 是否读取到了数据帧
    # frame 数据桢
    ret, frame = video.read()
    if ret:
        cv2.imshow('frame', frame)
    if cv2.waitKey(delay) == 27:
        break

# 释放图片资源
video.release()
cv2.destroyAllWindows()

案例:在视频上画圆

import cv2

# 记录是否开始画圆
drawing = False
points = []
def draw_circle(event, x, y, flags, param):
    global drawing
    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        points.append((x, y))

    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False

    elif event == cv2.EVENT_MOUSEMOVE:
        drawing = False
        
video = cv2.VideoCapture("../video/1.mp4")
if not video.isOpened():
    print("视频未打开")
    exit()
# 获取视频帧率
fps = video.get(cv2.CAP_PROP_FPS)
# 计算桢间延迟,播放速度
delay = int(1000 / fps)
cv2.namedWindow("frame")
cv2.setMouseCallback("frame",draw_circle)

while True:
    ret, frame = video.read()
    if ret:
        if points:
            for point in points:
                cv2.circle(frame, point, 15, (0, 0, 255), 5)
        cv2.imshow('frame', frame)
    if cv2.waitKey(delay) == 27:
        break

# 释放资源
video.release()
cv2.destroyAllWindows()
Logo

「智能机器人开发者大赛」官方平台,致力于为开发者和参赛选手提供赛事技术指导、行业标准解读及团队实战案例解析;聚焦智能机器人开发全栈技术闭环,助力开发者攻克技术瓶颈,促进软硬件集成、场景应用及商业化落地的深度研讨。 加入智能机器人开发者社区iRobot Developer,与全球极客并肩突破技术边界,定义机器人开发的未来范式!

更多推荐