一、文章介绍

1、本文主要介绍opencv的绘图功能以及鼠标与图像界面的交互功能。
2、包含直线、矩形、圆形的绘制。
3、opencv鼠标回调功能介绍。
4、案例:鼠标和键盘配合在图像中绘制图形。
效果展示:
在这里插入图片描述
5、案例:鼠标点击显示图像当前位置的像素和坐标。
效果展示:
在这里插入图片描述

6、案例:删除上一次鼠标绘制及一次性清空所有鼠标绘制。
效果展示:
在这里插入图片描述

二、opencv绘制直线、矩形、圆形

1、cv.line()

在这里插入图片描述
【1】img指要绘制的图形,可以是空白的图像,也可以是读取的图像
【2】pt1和pt2表示要绘制直线的两个端点的坐标,(横坐标,纵坐标)表示
【3】color表示颜色,(B,G,R),如果是灰度图,只需传一个标量值。
【4】thickness: 图形边界的厚度。如果传 -1 就是像圆这样的闭合图形,它将填充形状。 默认 thickness = 1
【5】lineType:线条类型,如 8 连接,抗锯齿线等。默认情况下,它是 8 连接。cv.LINE_AA 画出抗锯齿线,非常好看的曲线。
【6】shift表示坐标单位表示的像素的个数(2^shift),默认是0,坐标1表示1个像素,如果是1,表示1个坐标2两个像素,精度就是0.5。

2、cv.circle()

在这里插入图片描述

3、cv.rectangle()

在这里插入图片描述
pt1和pt2分别表示矩形的左上角和右下角

4、在图像上绘制直线、矩形和圆形

代码:


import cv2 as cv
img = cv.imread('data\gui\starry_night.jpg')
# 画一条 5px 宽的蓝色对角线
cv.line(img,(0,0),(200,300),(0,255,0),5)
cv.rectangle(img,(200,300),(300,500),(255,0,0),3)
cv.circle(img,(300,300), 50, (0,0,255), -1)
cv.imshow('img',img)
k=cv.waitKey(0)
if k == 27: # ESC 退出
    cv.destroyAllWindows()

效果:

5、cv.ellipse()(在空白画布上绘制椭圆)

在这里插入图片描述
在opencv-python中,有两种方式绘制椭圆

(1)img = cv.ellipse( img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType[, shift]]] )

center 是椭圆的中心点,axes 是长轴和短轴的长度,angle 是椭圆的旋转角度,startAngle 和 endAngle 定义了绘制的角度范围。startAngle和endAngle 为0和360时,绘制的才是完整的椭圆。
代码:

import cv2 as cv
import numpy as np

# 创建一个黑色图像
img = np.zeros((400, 400, 3), dtype=np.uint8)

# 定义椭圆的参数
center = (200, 200)  # 中心点
axes = (100, 50)     # 半轴长度 (长轴, 短轴)
angle = 30           # 旋转角度
startAngle = 0       # 起始角度
endAngle = 360       # 结束角度
color = (255, 0, 0)  # 颜色 (B, G, R)
thickness = 2        # 线条厚度

# 绘制椭圆
cv.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness)

# 显示图像
cv.imshow("Ellipse Example", img)
cv.waitKey(0)
cv.destroyAllWindows()

效果:
在这里插入图片描述
如果startAngle和endAngle 为0和90:
在这里插入图片描述
表明0度为横坐标方向,顺时针为角度增加。

(2)img = cv.ellipse( img, box, color[, thickness[, lineType]]

使用一个外接矩形的参数 box,box指的是旋转矩形,其中包含中心点的坐标、宽度和高度、旋转角度。
代码:

import cv2 as cv
import numpy as np

# 创建一个黑色图像
img = np.zeros((400, 400, 3), dtype=np.uint8)

# 定义 旋转矩阵RotatedRect 的参数
center = (200, 200)  # 中心点
size = (130, 80)     # (宽度, 高度)
angle = 30           # 旋转角度
# 创建 RotatedRect
rotated_rect = ((center[0], center[1]), (size[0], size[1]), angle)
color = (0, 255, 0)         # 颜色 (B, G, R)
thickness = 2               # 线条厚度

# 绘制椭圆
cv.ellipse(img, rotated_rect, color,thickness)

# 显示图像
cv.imshow("Ellipse Example", img)
cv.waitKey(0)
cv.destroyAllWindows()

效果:

6、cv.putText()

在这里插入图片描述
【1】img: 要在其上绘制文本的图像。
【2】text: 要绘制的文本字符串。
【3】org: 文本的左下角位置,格式为 (x, y)。
【4】fontFace: 字体类型,可以是以下常量之一:
cv.FONT_HERSHEY_SIMPLEX
cv.FONT_HERSHEY_PLAIN
cv.FONT_HERSHEY_DUPLEX
cv.FONT_HERSHEY_COMPLEX
cv.FONT_HERSHEY_TRIPLEX
cv.FONT_HERSHEY_COMPLEX_SMALL
cv.FONT_HERSHEY_SCRIPT_SIMPLEX
cv.FONT_HERSHEY_SCRIPT_COMPLEX
【5】fontScale: 字体大小的缩放因子。
【6】color: 文本颜色,格式为 (B, G, R)。
【7】thickness: 线条厚度(可选,默认为 1)。
【8】ineType: 线条类型(可选,默认为 LINE_8)。
【9】bottomLeftOrigin: 如果为 true,则文本的原点在左下角(可选,默认为 false)
代码:

import cv2 as cv
import numpy as np

# 创建一个黑色图像
img = np.zeros((400, 600, 3), dtype=np.uint8)

# 定义文本内容和属性
text = "Hello, OpenCV!"
org = (50, 200)  # 文本的左下角位置
fontFace = cv.FONT_HERSHEY_SIMPLEX
fontScale = 1
color = (255, 255, 255)  # 白色
thickness = 2

# 在图像上绘制文本
cv.putText(img, text, org, fontFace, fontScale, color, thickness)

# 显示图像
cv.imshow("Text Example", img)
cv.waitKey(0)
cv.destroyAllWindows()

效果:
在这里插入图片描述

三、opencv鼠标回调功能

OpenCV 的鼠标回调功能允许用户在图像窗口中处理鼠标事件,例如点击、移动、按下和释放鼠标键。这种功能在图形用户界面(GUI)开发和交互式应用程序中非常有用。

1、基本用法

(1)创建窗口:使用 cv2.namedWindow() 创建一个可用于接收鼠标事件的窗口。

(2)定义鼠标回调函数:创建一个回调函数,处理不同的鼠标事件。在这个函数中,可以获取鼠标的位置、按键状态等信息。

(3)注册回调函数:使用 cv2.setMouseCallback() 将定义的回调函数与窗口绑定。

(4)显示图像并等待事件:使用 cv2.imshow() 显示图像,然后使用 cv2.waitKey() 等待用户输入.

3、注册回调函数

在这里插入图片描述
其中,参数一是需要交互的窗口的名称,参数二是回调函数的名称,参数三是一个指向用户自定义数据的指针,可以用来在回调函数中传递额外的信息,可以将任何类型的数据传递给回调函数,以便在处理鼠标事件时使用,默认为 0(空指针),如果不需要传递额外数据,可以省略或传递 nullptr。

回调函数格式如下:
在这里插入图片描述
(1)event: 鼠标事件类型(如 EVENT_LBUTTONDOWN 表示左键按下)。
(2)x, y: 鼠标事件发生时的坐标。
(3)flags: 一些额外的标志(如 SHIFT、CTRL 键是否按下)。
(4)userdata: 传递给回调函数的用户数据。

4、鼠标事件类型

在 OpenCV 中,有多种鼠标事件可以使用,常用的包括:
cv2.EVENT_LBUTTONDOWN: 左键按下
cv2.EVENT_RBUTTONDOWN: 右键按下
cv2.EVENT_MOUSEMOVE: 鼠标移动
cv2.EVENT_LBUTTONUP: 左键释放
cv2.EVENT_RBUTTONUP: 右键释

四、案例:鼠标和键盘配合在图像中绘制图形。

1、代码


import numpy as np
import cv2 as cv
drawing = False # 如果 True 是鼠标按下
mode = True # 如果 True,画矩形,按下‘m’切换到画圆点
ix,iy = -1,-1
# 鼠标回调函数
def draw_circle(event,x,y,flags,param):
    global ix,iy,drawing,mode
    if event == cv.EVENT_LBUTTONDOWN:
        drawing = True
        ix,iy = x,y
    elif event == cv.EVENT_MOUSEMOVE:
        if drawing == True:
            if mode == True:
                cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
            else:
                cv.circle(img,(x,y),1,(0,0,255),-1)
    elif event == cv.EVENT_LBUTTONUP:
        drawing = False
        if mode == True:
            cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
        else:
            cv.circle(img,(x,y),10,(0,0,255),-1)


if __name__ == "__main__":
    img = np.zeros((512, 512, 3), np.uint8)
    cv.namedWindow('image')
    cv.setMouseCallback('image', draw_circle)
    while (1):
        cv.imshow('image', img)
        k = cv.waitKey(1) & 0xFF
        if k == ord('c'):
            mode = not mode
        elif k == 27:
            break

    cv.destroyAllWindows()


2、思路

代码中定义drawing变量判断鼠标是否按下。使用mode变量表示键盘’c’键是否按下。
按下鼠标左键,画一个绿色的点,移动鼠标绘制绿色的矩形。
按下‘c’键盘按键后,切换到画圆形。鼠标左键按下,绘制一个半径为5个像素点的圆形,鼠标滑动,连续绘制半径为1个像素点的圆形。

五、案例:鼠标点击显示图像当前位置的像素和坐标

1、代码



import numpy as np
import cv2 as cv
drawing = False # 如果 True 是鼠标按下
ix,iy = -1,-1
# 鼠标回调函数
def draw_circle(event,x,y,flags,param):
    global ix, iy, drawing
    if event == cv.EVENT_LBUTTONDOWN:
        drawing = True
        ix,iy = x,y
    elif event == cv.EVENT_LBUTTONUP:
        if drawing==True:
            cv.putText(img, f'Coordinates: ({x}, {y})', (x, y), cv.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
            cv.putText(img, f'value: ({img[y, x]})', (x, y + 25), cv.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            cv.circle(img, (x, y), 2, (0, 0, 255), -1)
            drawing = False

if __name__ == "__main__":
    img = cv.imread('data\gui\starry_night.jpg')
    cv.namedWindow('image')
    cv.setMouseCallback('image', draw_circle)
    while (1):
        cv.imshow('image', img)
        k = cv.waitKey(1) & 0xFF
        if k == 27:
            break
    cv.destroyAllWindows()

2、思路

使用drawing标识是否绘制,鼠标左键按下时,表示需要绘制,鼠标左键松开时,绘制坐标点和像素点,然后将drawing置为False表示绘制完毕。

六、案例:删除上一次鼠标绘制及一次性清空所有鼠标绘制

1、代码

import cv2 as cv
import numpy as np

# 读取图像
img = cv.imread('data\gui\starry_night.jpg')
if img is None:
    print("Error: Could not read the image.")
    exit()

# 保存原始图像
original_img = img.copy()
drawing = False  # 标记是否正在绘制
history = []  # 用于存储历史图像状态

def mouse_callback(event, x, y, flags, param):
    global img, original_img, drawing, history

    if event == cv.EVENT_LBUTTONDOWN:  # 左键按下
        # 保存当前状态到历史记录
        history.append(img.copy())
        drawing = True


    elif event == cv.EVENT_LBUTTONUP:  # 左键抬起
        drawing = False
        cv.circle(img, (x, y), 20, (0, 255, 0), -1)  # 绘制绿色圆形

    elif event == cv.EVENT_RBUTTONDOWN:  # 右键按下
        img = original_img.copy()  # 清空图像,恢复为原始图像
        history.clear()  # 清空历史记录

# 创建窗口并设置鼠标回调
cv.namedWindow('image')
cv.setMouseCallback('image', mouse_callback)

while True:
    cv.imshow('image', img)

    key = cv.waitKey(1) & 0xFF
    if key == ord('q'):  # 按 'q' 键退出
        break
    elif key == ord('u'):  # 按 'u' 键撤销上一步
        if history:
            img = history.pop()  # 撤销上一步

cv.destroyAllWindows()

2、思路

将原始图像拷贝备份。每次绘制之前,将当前图片保存,如果按下’u’,则删除一张图像,如果右键按下,显示原始图像。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部