绘图功能
首先需要创建一个背景来承接绘制的图像
img = np.zeros((512, 512, 3), np.uint8) # 创建黑色的图像
- 画线
此处img表示绘制的图像,(0, 0)和(511, 511)是线段的两点坐标,(255, 0, 0)为BGR颜色表示法,5表示厚度cv.line(img, (0, 0), (511, 511), (255, 0, 0), 5) # 绘制一条厚度为5的蓝色对角线
- 画矩形
(384, 0)和(510, 128)是矩形两对角坐标,BGR,厚度cv.rectangle(img, (384, 0), (510, 128), (0, 255, 0), 3) # 画矩形
- 画圆圈
(447, 63)为圆中心坐标, 63为半径,(0, 0, 255)BGR,-1表示填充而非线的厚度cv.circle(img, (447, 63), 63, (0, 0, 255), -1) # 画圆圈
- 画椭圆
(256, 256)为中心坐标, (100, 50)长轴和短轴长度, 0为图像逆时针旋转的角度angle, 0和180表示图像从主轴顺时针方向的开始角度和结束角度,这里的从0到180即表示椭圆的下半圆, 255也可以和前面一样用BGR表示, -1表示填充cv.ellipse(img, (256, 256), (100, 50), 0, 0, 180, 255, -1) # 画椭圆
- 画多边形
# 画多边形,需要包含了顶点坐标的顶点集数据 pts = np.array([[10, 5], [20, 30], [70, 20], [50, 10]], np.int32) pts = pts.reshape((-1, 1, 2)) # 从-1开始,步长为1, 到2结束 cv.polylines(img, [pts], True, (0, 255, 255)) # 绘制多条线,true/false表示是否为闭合图像
- 添加文字
# 向图像添加文本,参数为:文字数据、位置坐标、字体类型、字体比例、常规内容LINE_AA font = cv.FONT_HERSHEY_SIMPLEX cv.putText(img, 'OpenCV', (10, 500), font, 4, (255, 255, 255), 2, cv.LINE_AA) plt.imshow(img, cmap='gray', interpolation='bicubic') plt.show()
最终结果如下:
读取鼠标操作
可以使用一下代码查看可用的鼠标事件
events = [i for i in dir(cv) if 'EVENT' in i]
print(events)
整理的结果为:
(1)event:
EVENT_MOUSEMOVE 0 #滑动
EVENT_LBUTTONDOWN 1 #左键点击
EVENT_RBUTTONDOWN 2 #右键点击
EVENT_MBUTTONDOWN 3 #中键点击
EVENT_LBUTTONUP 4 #左键放开
EVENT_RBUTTONUP 5 #右键放开
EVENT_MBUTTONUP 6 #中键放开
EVENT_LBUTTONDBLCLK 7 #左键双击
EVENT_RBUTTONDBLCLK 8 #右键双击
EVENT_MBUTTONDBLCLK 9 #中键双击
(2)x,y:
x,y,代表鼠标位于窗口的(x,y)坐标位置
(3)flags:
代表鼠标的拖拽事件,以及键盘鼠标联合事件
EVENT_FLAG_LBUTTON 1 #左鍵拖曳
EVENT_FLAG_RBUTTON 2 #右鍵拖曳
EVENT_FLAG_MBUTTON 4 #中鍵拖曳
EVENT_FLAG_CTRLKEY 8 #(8~15)按Ctrl不放事件
EVENT_FLAG_SHIFTKEY 16 #(16~31)按Shift不放事件
EVENT_FLAG_ALTKEY 32 #(32~39)按Alt不放事件
鼠标回调函数有特定的格式,在所有地方使用都相同。这里简单实现一个鼠标双击画圆的鼠标回调函数:
def draw_circle(event, x, y, flags, param):
if event == cv.EVENT_LBUTTONDBLCLK: # 双击
cv.circle(img, (x, y), 100, (255, 255, 255), -1)
创建一个背景,并设置鼠标回调
img = np.zeros((512, 512, 3), np.uint8) # 创建一个黑色的图像
cv.namedWindow('image')
cv.setMouseCallback('image', draw_circle)
while True:
cv.imshow('image', img)
if cv.waitKey(20) & 0xFF == 27:
break
cv.destroyAllWindows()
效果如下:
更进一步的实现
可以考虑多加入鼠标的判断调用来实现更复杂的操作
drawing = False # 是否画图的标志
mode = True # 画矩形/圆形
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:
if mode:
cv.rectangle(img, (ix, iy), (x, y), (255, 255, 255), 1)
else:
r = int(math.sqrt((x-ix)**2 + (y-iy)**2))
cv.circle(img, (ix, iy), r, (0, 0, 255), 1)
elif event == cv.EVENT_LBUTTONUP: # 放开鼠标
drawing = False
if mode:
cv.rectangle(img, (ix, iy), (x, y), (255, 255, 255), -1)
else:
r = int(math.sqrt((x - ix) ** 2 + (y - iy) ** 2))
cv.circle(img, (ix, iy), r, (0, 0, 255), -1)
img = np.zeros((512, 512, 3), np.uint8) # 创建一个黑色的图像
cv.namedWindow('image')
cv.setMouseCallback('image', draw_circle)
while True:
cv.imshow('image', img)
if cv.waitKey(20) & 0xFF == 27:
break
cv.destroyAllWindows()
注意,这里我对画圆函数进行了修改,是根据鼠标拖动距离作为半径来画圆,而不是像画笔一样每次都画圆点,效果如下: