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

1_bit 2021-01-14 01:47:31 4609

一、学习目标

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

目录

[python opencv 计算机视觉零基础到实战] 一、opencv的helloworld
.
.
.
[python opencv 计算机视觉零基础到实战] 十四 直方图颜色提鲜
.
.
.

[python opencv 计算机视觉零基础到实战] 十八、用鼠标进行画画

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

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()

以上代码使用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)

结果如下:

2.2 制作一个简单的绘画板

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

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

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

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

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

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

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

drawing=False
sx,sy=0,0

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

global sx,sy,drawing

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

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

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

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

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

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

所有完整的代码如下:

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. 通过事件以及灵活运用绘图函数制作了一个简易的绘画板
声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
1_bit
红包 93 8 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
1_bit
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区