[python opencv 计算机视觉零基础到实战] 十九、简易绘画板制作

举报
1_bit 发表于 2021/04/17 23:13:15 2021/04/17
【摘要】 一、学习目标 了解事件编写一个简易绘画板 二、了解如何制作简易绘画板 2.1 了解鼠标多种事件 上一节我们简单的使用opencv的图形绘制方法,用鼠标绘制了一些内容。上一节所响应的是简单的双击事件EVENT_LBUTTONDBLCLK,在OpenCV的鼠标事件中还有很多。以下将列举出来: EVENT_MOUSEMOVE:鼠标滑动EVENT_LBUTTONDOW...

一、学习目标

  1. 了解事件
  2. 编写一个简易绘画板

二、了解如何制作简易绘画板

2.1 了解鼠标多种事件

上一节我们简单的使用opencv的图形绘制方法,用鼠标绘制了一些内容。上一节所响应的是简单的双击事件EVENT_LBUTTONDBLCLK,在OpenCV的鼠标事件中还有很多。以下将列举出来:

  • EVENT_MOUSEMOVE:鼠标滑动
  • EVENT_LBUTTONDOWN:左键单击
  • EVENT_RBUTTONDOWN:右键单击
  • EVENT_MBUTTONDOWN:中间单击
  • EVENT_LBUTTONUP:左键释放
  • EVENT_RBUTTONUP:右键释放
  • EVENT_MBUTTONUP:中键释放
  • EVENT_LBUTTONDBLCLK:左键双击
  • EVENT_RBUTTONDBLCLK:右键双击
  • EVENT_MBUTTONDBLCLK:中键双击

以上事件在setMouseCallback函数回调后将会传到所执行的函数中,并且以event参数进行对应,取值通过event参数进行取值。

首先我们对一些事件进行监测,先尝试检测CV_EVENT_MOUSEMOVE鼠标滑动事件。代码如下:

import cv2
import numpy as np
def listing(event,x,y,flags,param): if event==cv2.EVENT_MOUSEMOVE: print('EVENT_MOUSEMOVE',' x:',x,' y:',y)
img=np.zeros((600,600,3),np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',listening)
while(1): cv2.imshow('image',img) if cv2.waitKey(20)&0xFF==27: break
cv2.destroyAllWindows()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

以上代码使用listing作为回调后的处理,并且当事件为EVENT_MOUSEMOVE时将会输出事件名以及当前鼠标所在的x和y坐标的位置。

结果如下:
这时我们可以对所有的事件都进行监听,这时候修改listen函数就可以了:

def listening(event,x,y,flags,param): if event==cv2.EVENT_MOUSEMOVE: print('EVENT_MOUSEMOVE 鼠标滑动',' x:',x,' y:',y) elif event==cv2.EVENT_LBUTTONDOWN: print('EVENT_LBUTTONDOWN 左键单击',' x:',x,' y:',y) elif event==cv2.EVENT_RBUTTONDOWN: print('EVENT_RBUTTONDOWN 右键单击',' x:',x,' y:',y) elif event==cv2.EVENT_MBUTTONDOWN: print('EVENT_MBUTTONDOWN 中间单击',' x:',x,' y:',y) elif event==cv2.EVENT_LBUTTONUP: print('EVENT_LBUTTONUP 左键释放',' x:',x,' y:',y) elif event==cv2.EVENT_RBUTTONUP: print('EVENT_RBUTTONUP 右键释放',' x:',x,' y:',y) elif event==cv2.EVENT_MBUTTONUP: print('EVENT_MBUTTONUP 中键释放',' x:',x,' y:',y) elif event==cv2.EVENT_LBUTTONDBLCLK: print('EVENT_LBUTTONDBLCLK 左键双击',' x:',x,' y:',y) elif event==cv2.EVENT_RBUTTONDBLCLK: print('EVENT_RBUTTONDBLCLK 右键双击',' x:',x,' y:',y) elif event==cv2.EVENT_MBUTTONDBLCLK: print('EVENT_MBUTTONDBLCLK 中键双击',' x:',x,' y:',y)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

结果如下:

2.2 制作一个简单的绘画板

首先我们对绘制一个拖拽绘制板功能做一个行为分析。我们正常进行拖拽画矩形,一般是按下左键,并且不放手,移动鼠标进行矩形的绘制,直到拖拽至我们觉得合适的位置后,我们开始松开鼠标。

在以上的绘制行为中,一共有几个鼠标事件。有按下鼠标左键事件EVENT_LBUTTONDOWN、鼠标移动事件EVENT_MOUSEMOVE、鼠标左键释放事件EVENT_LBUTTONUP。我们在按下鼠标左键的时候,从当前鼠标的x与y坐标开始绘制矩形,直到我们松开鼠标后停止绘制。

我们写一个函数作为回调的处理:

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

  
 
  • 1

随后我们在鼠标按下左键的时候需要记住x与y的坐标位置,并且表示开始绘制,需要一个变量表示绘制状态开启:

if event==cv2.EVENT_LBUTTONDOWN: drawing=True sx,sy=x,y

  
 
  • 1
  • 2
  • 3

注意,由于回调函数每次循环时都会进行调用,若drawing此次为True后下一次不能直接进入绘制,这个时候需要把drawing、sx、sy都设置成全局变量:

drawing=False
sx,sy=0,0

  
 
  • 1
  • 2

并且在回调处理的函数中需要加入关键字进行声明是全局变量:

global sx,sy,drawing

  
 
  • 1

接下来我们应该判断当前是否已经是按下鼠标左键并且进行了拖拽移动,这两个状态是并列的,所以写个elif语句进行判断:

elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:

  
 
  • 1

这个时候在该判断中,使用if语句判断是否已经按下左键后开启了绘制,防止bug的出现,若已经开启了绘制则进行绘制矩形:

cv2.rectangle(img,(sx,sy),(x,y),(0,255,0),-1)

  
 
  • 1

如上代码中为什么起始绘制点是sx与sy呢?那是因为我们按下了鼠标左键后的那个点是绘制起始点,从那个点开始绘制矩形到当前鼠标移动到的x和y坐标处,这样由于每次都覆盖掉原来的图像造成一种错觉,就是在拖拽进行绘制图像,并且进行填充,颜色为(0,255,0)。由于绘制状态不能一直开启,若直接进入了按下左脚与移动时由于保留了上次绘制的绘制开启,那么会造成初始绘制点的丢失,所以我们还需要判断当鼠标左键释放弹起后把绘制状态改为Fasle。代码如下:

elif event==cv2.EVENT_LBUTTONUP: drawing==False

  
 
  • 1
  • 2

所有完整的代码如下:

import cv2
import numpy as np

drawing=False
sx,sy=0,0

def draw(event,x,y,flags,param): global sx,sy,drawing if event==cv2.EVENT_LBUTTONDOWN: drawing=True sx,sy=x,y elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON: if drawing==True: cv2.rectangle(img,(sx,sy),(x,y),(0,255,0),-1) elif event==cv2.EVENT_LBUTTONUP: drawing==False
img=np.zeros((600,600,3),np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw)
while(1): cv2.imshow('image',img) if cv2.waitKey(20)&0xFF==27: break
cv2.destroyAllWindows()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

结果如下:
该系列首发于ebaina

三、总结

  1. 了解了多个鼠标事件
  2. 通过事件以及灵活运用绘图函数制作了一个简易的绘画板

文章来源: blog.csdn.net,作者:1_bit,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/A757291228/article/details/112596638

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。