从opencv-python入门opencv--GUI功能之绘图和鼠标操作
- 一、文章介绍
- 二、opencv绘制直线、矩形、圆形
-
- 1、cv.line()
- 2、cv.circle()
- 3、cv.rectangle()
- 4、在图像上绘制直线、矩形和圆形
- 5、cv.ellipse()(在空白画布上绘制椭圆)
-
- [(1)img = cv.ellipse( img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType[, shift]]] )](#(1)img = cv.ellipse( img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType[, shift]]] ))
- [(2)img = cv.ellipse( img, box, color[, thickness[, lineType]]](#(2)img = cv.ellipse( img, box, color[, thickness[, lineType]])
- 6、cv.putText()
- 三、opencv鼠标回调功能
- 四、案例:鼠标和键盘配合在图像中绘制图形。
- 五、案例:鼠标点击显示图像当前位置的像素和坐标
- 六、案例:删除上一次鼠标绘制及一次性清空所有鼠标绘制
一、文章介绍
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、在图像上绘制直线、矩形和圆形
代码:
python
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时,绘制的才是完整的椭圆。
代码:
python
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指的是旋转矩形,其中包含中心点的坐标、宽度和高度、旋转角度。
代码:
python
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)
代码:
python
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、代码
python
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、代码
python
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、代码
python
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',则删除一张图像,如果右键按下,显示原始图像。