首页专栏详情
打赏
如何灵活运用绘图函数制作了一个简易的绘画板~
如何灵活运用绘图函数制作了一个简易的绘画板~
易百纳技术社区 来自远方 2022-07-08 09:47:17

一、学习目标

  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. 通过事件以及灵活运用绘图函数制作了一个简易的绘画板
934
收藏
点赞
打赏
共1人已赏
贫穷,流下没钱的泪水。。。
评论
0个
内容存在敏感词
相关专栏
打赏作者
易百纳技术社区
来自远方
您的支持将鼓励我继续创作!
打赏金额:
¥1 易百纳技术社区
¥5 易百纳技术社区
¥10 易百纳技术社区
¥50 易百纳技术社区
¥100 易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区 微信支付
易百纳技术社区
打赏成功!

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

审核成功

发布时间设置
发布时间:

审核失败

失败原因
备注
Loading...
易百纳技术社区
确定要删除此文章、专栏、评论吗?
确定
取消
易百纳技术社区
易百纳技术社区
在专栏模块发布专栏,可获得其他E友的打赏
易百纳技术社区
回答悬赏问答,被题主采纳后即可获得悬赏金
易百纳技术社区
在上传资料时,有价值的资料可设置为付费资源
易百纳技术社区
达到一定金额,收益即可提现~
收益也可用来充值ebc,下载资料、兑换礼品更容易
易百纳技术社区
活动规则
  • 1.周任务为周期性任务,每周周一00:00刷新,上周完成的任务不会累计到本周,本周需要从头开始任务,当前任务完成后才可以完成下一个任务
  • 2.发布的专栏与资料需要与平台的板块有相关性,禁止注水,专栏/资料任务以审核通过的篇数为准
  • 3.任务完成后,现金奖励直接打款到微信账户;EBC/收益将自动发放到个人账户,可前往“我的钱包”查看;其他奖励请联系客服兑换
  • 4.每周最后三个任务将会有以下奖品掉落:社区热卖开发板、小米音响、视频年度会员、京东卡、华为手机等等
易百纳技术社区
升级提醒
易百纳技术社区

恭喜您由入门

社区送出礼品一份

请填写您的收件地址,礼品将在3个工作日寄出

易百纳技术社区