问题描述:
创建一个画板,可以自选各种颜色的画笔绘画各种图形。
import cv2
import numpy as np
def nothing(x):
pass
# 当鼠标按下时变为 True
drawing = False
# 如果 mode 为 true 绘制矩形。按下'm' 变成绘制曲线。
mode = True
ix, iy = -1, -1
# 创建回调函数
def draw_circle(event, x, y, flags, param):
r = cv2.getTrackbarPos('R', 'image')
g = cv2.getTrackbarPos('G', 'image')
b = cv2.getTrackbarPos('B', 'image')
color = (b, g, r)
global ix, iy, drawing, mode
# 当按下左键是返回起始位置坐标
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True
ix, iy = x, y
# 当鼠标左键按下并移动是绘制图形。 event 可以查看移动, flag 查看是否按下
elif event == cv2.EVENT_MOUSEMOVE and flags == cv2.EVENT_FLAG_LBUTTON:
if drawing == True:
if mode == True:
cv2.rectangle(img, (ix, iy), (x, y), color, -1)
else:
# 绘制圆圈,小圆点连在一起就成了线, 3 代表了笔画的粗细
cv2.circle(img, (x, y), 3, color, -1)
# 下面注释掉的代码是起始点为圆心,起点到终点为半径的
# r=int(np.sqrt((x-ix)**2+(y-iy)**2))
# cv2.circle(img,(x,y),r,(0,0,255),-1)
# 当鼠标松开停止绘画。
elif event == cv2.EVENT_LBUTTONUP:
drawing == False
# if mode==True:
# cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
# else:
# cv2.circle(img,(x,y),5,(0,0,255),-1)
img = np.zeros((512, 512, 3), np.uint8)
cv2.namedWindow('image')
cv2.createTrackbar('R', 'image', 0, 255, nothing)
cv2.createTrackbar('G', 'image', 0, 255, nothing)
cv2.createTrackbar('B', 'image', 0, 255, nothing)
cv2.setMouseCallback('image', draw_circle)
while (1):
cv2.imshow('image', img)
k = cv2.waitKey(1) & 0xFF
if k == ord('m'):
mode = not mode
elif k == 27:
break
逐行分析上述代码的逻辑结构。
问题解答:
以下是逐行分析上述代码的逻辑结构:
-
导入库:
import cv2 import numpy as np
导入 OpenCV 和 NumPy 库,用于图像处理和数组操作。
-
定义空的回调函数:
def nothing(x): pass
定义一个空的回调函数
nothing
,用于滑块的回调,不执行任何操作。 -
初始化变量:
drawing = False mode = True ix, iy = -1, -1
drawing
:布尔值,指示是否正在绘制。mode
:布尔值,决定绘制形状的类型(矩形或曲线)。ix, iy
:鼠标点击的起始坐标,初始化为 -1。
-
创建绘图回调函数:
def draw_circle(event, x, y, flags, param):
定义一个名为
draw_circle
的函数,用于处理鼠标事件。 -
获取颜色值:
r = cv2.getTrackbarPos('R', 'image') g = cv2.getTrackbarPos('G', 'image') b = cv2.getTrackbarPos('B', 'image') color = (b, g, r)
从滑块获取当前的 RGB 值,并将其存储为
color
元组,顺序为 (B, G, R)。 -
处理鼠标事件:
-
鼠标左键按下:
if event == cv2.EVENT_LBUTTONDOWN: drawing = True ix, iy = x, y
当左键按下时,设置
drawing
为True
并记录起始坐标。 -
鼠标移动:
elif event == cv2.EVENT_MOUSEMOVE and flags == cv2.EVENT_FLAG_LBUTTON: if drawing == True: if mode == True: cv2.rectangle(img, (ix, iy), (x, y), color, -1) else: cv2.circle(img, (x, y), 3, color, -1)
如果鼠标左键按下并移动:
- 若
mode
为True
,绘制矩形。 - 否则,绘制小圆点(即线条)。
- 若
-
鼠标左键松开:
elif event == cv2.EVENT_LBUTTONUP: drawing == False
这里存在一个错误:应使用
drawing = False
,而不是drawing == False
。
-
-
创建图像:
img = np.zeros((512, 512, 3), np.uint8)
创建一个 512x512 的全黑图像,数据类型为无符号 8 位整数。
-
创建窗口:
cv2.namedWindow('image')
创建一个名为
'image'
的窗口,用于显示图像。 -
创建滑块:
cv2.createTrackbar('R', 'image', 0, 255, nothing) cv2.createTrackbar('G', 'image', 0, 255, nothing) cv2.createTrackbar('B', 'image', 0, 255, nothing)
创建三个滑块,用于调整红色、绿色和蓝色通道的强度,范围从 0 到 255。
-
设置鼠标回调:
cv2.setMouseCallback('image', draw_circle)
设置窗口
'image'
的鼠标回调函数为draw_circle
,用于处理鼠标事件。 -
显示窗口循环:
while (1): cv2.imshow('image', img) k = cv2.waitKey(1) & 0xFF if k == ord('m'): mode = not mode elif k == 27: break
进入一个无限循环:
- 不断显示当前的图像。
- 检查键盘输入:如果按下
m
切换绘制模式;如果按下Esc
键退出循环。
-
关闭窗口:
cv2.destroyAllWindows()
循环结束后,关闭所有 OpenCV 创建的窗口。
总结
该代码实现了一个简单的图形绘制程序,用户可以通过鼠标在图像上绘制矩形或线条,同时可以通过滑块动态调整颜色。