win10+Python3.7.3+OpenCV3.4.1入门学习(十九 绘图及交互)————19.2 鼠标交互

Python版本是Python3.7.3,OpenCV版本OpenCV3.4.1,开发环境为PyCharm

19.2 鼠标交互

当用户触发鼠标事件时,我们希望对该事件做出响应。例如,用户单击鼠标,我们就画一个圆。通常的做法是,创建一个OnMouseAction()响应函数,将要实现的操作写在该响应函数内。响应函数是按照固定的格式创建的,其格式为:

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

式中:
● event表示触发了何种事件,具体事件如下表所示。
在这里插入图片描述

● x, y代表触发鼠标事件时,鼠标在窗口中的坐标(x, y)。
● flags代表鼠标的拖曳事件,以及键盘鼠标联合事件,如下表所示。

在这里插入图片描述

● param为函数ID,标识所响应的事件函数,相当于自定义一个OnMouseAction()函数的ID。
● OnMouseAction为响应函数的名称,该名称可以自定义。
定义响应函数以后,要将该函数与一个特定的窗口建立联系(绑定),让该窗口内的鼠标触发事件时,能够找到该响应函数并执行。要将函数与窗口绑定,可以通过函数cv2.setMouseCallback()实现,其基本语法格式是:

cv2.setMouseCallback(winname, onMouse)

式中:
● winname为绑定的窗口名。
● onMouse为绑定的响应函数名。

eg1:设计一个程序,对触发的鼠标事件进行判断。
代码如下:

import cv2
import numpy as np
def Demo(event,x,y,flags,param):
    if event == cv2.EVENT_LBUTTONDOWN:
        print("单击了鼠标左键")
    elif event==cv2.EVENT_RBUTTONDOWN :
        print("单击了鼠标右键")
    elif flags==cv2.EVENT_FLAG_LBUTTON:
        print("按住左键拖动了鼠标")
    elif event==cv2.EVENT_MBUTTONDOWN :
        print("单击了中间键")
#创建名称为Demo的响应(回调)函数OnMouseAction
#将回调函数Demo与窗口“Demo19.9”建立连接
img = np.ones((300,300,3),np.uint8)*255
cv2.namedWindow('Demo19.9')
cv2.setMouseCallback('Demo19.9',Demo)     
cv2.imshow('Demo19.9',img)
cv2.waitKey()
cv2.destroyAllWindows()

运行程序,在创建的窗口Demo19.9内:
● 单击鼠标左键,会触发单击左键事件“cv2.EVENT_LBUTTONDOWN”。
● 单击鼠标右键,会触发单击右键事件“cv2.EVENT_RBUTTONDOWN”。
● 单击鼠标中间键(滚轮),会触发单击中间键事件“cv2.EVENT_MBUTTONDOWN”
● 按住鼠标左键拖动鼠标,会依次触发单击左键事件“cv2.EVENT_LBUTTONDOWN”和左键拖动事件“cv2.EVENT_FLAG_LBUTTON”。
运行上述程序,先后单击左键、右键、滚轮、拖动鼠标,则程序运行结果如下图所示。
在这里插入图片描述

说明:可以通过下面的方法查看OpenCV所支持的鼠标事件:

import cv2
events=[i for i in dir(cv2) if 'EVENT'in i]
print(events)
19.2.1 简单示例

本节实现一个双击鼠标绘制矩形的简单程序。在该程序中,首先创建响应函数draw(),在该函数内编写代码,实现:当双击鼠标时,以当前位置为顶点绘制大小随机、颜色随机的矩形。通过函数cv2.setMouseCallback()将函数draw()和新建窗口“Demo19.10”绑定。

eg2:设计一个程序,当双击鼠标后,以当前位置为顶点绘制大小随机、颜色随机的矩形。
代码如下:

import cv2
import numpy as np
d = 400
def draw(event,x,y,flags,param):
    if event==cv2.EVENT_LBUTTONDBLCLK:
        p1x=x
        p1y=y
        p2x=np.random.randint(1,d-50)
        p2y=np.random.randint(1,d-50)
        color = np.random.randint(0,high = 256,size = (3,)).tolist()
        cv2.rectangle(img,(p1x,p1y),(p2x,p2y),color,2)
img = np.ones((d,d,3),dtype="uint8")*255
cv2.namedWindow('Demo19.10')
cv2.setMouseCallback('Demo19.10',draw)
while(1):
    cv2.imshow('Demo19.10',img)
    if cv2.waitKey(20)==27:
        break
cv2.destroyAllWindows()

运行程序,在图像内双击鼠标就会以当前位置为顶点绘制大小随机、颜色随机的矩形。下图是在图像的不同位置多次双击鼠标后的结果。
在这里插入图片描述

19.2.2 进阶示例

鼠标事件为用户与计算机之间的交互提供了接口,让用户能够非常灵活地与计算机之间实现交互。本节通过一个鼠标与键盘配合的例子,展示如何实现用户与计算机的交互。
eg3:设计一个交互程序,通过键盘与鼠标的组合控制显示不同的形状或文字。
代码如下:

import cv2
import numpy as np
thickness=-1
mode=1
d=400
def draw_circle(event,x,y,flags,param):
    if event==cv2.EVENT_LBUTTONDOWN:
        a=np.random.randint(1,d-50)
        r=np.random.randint(1,d/5)
        angle = np.random.randint(0,361)
        color = np.random.randint(0,high = 256,size = (3,)).tolist()
        if mode==1:
            cv2.rectangle(img,(x,y),(a,a),color,thickness)
        elif mode==2:
            cv2.circle(img,(x,y),r,color,thickness)
        elif mode==3:
            cv2.line(img,(a,a),(x,y),color,3)  
        elif mode==4:
            cv2.ellipse(img, (x,y), (100,150), angle, 0, 360,color,thickness)                  
        elif mode==5:
            cv2.putText(img,'OpenCV',(0,round(d/2)), 
                        cv2.FONT_HERSHEY_SIMPLEX, 2,color,5)    
img=np.ones((d,d,3),np.uint8)*255
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)
while(1):
    cv2.imshow('image',img)
    k=cv2.waitKey(1)&0xFF
    if k==ord('r'):
        mode=1
    elif k==ord('c'):
        mode=2
    elif k==ord('l'):
        mode=3
    elif k==ord('e'):
        mode=4
    elif k==ord('t'):
        mode=5
    elif k==ord('f'):
        thickness=-1
    elif k==ord('u'):
        thickness=3
    elif k==27:
        break   
cv2.destroyAllWindows()

运行程序,我们就可以通过键盘控制单击鼠标左键时在图像内显示的对象。不同的按键,控制不同的显示内容:
● 按下“r”键后,在窗体内单击鼠标左键,会显示以当前鼠标位置为顶点,以任意位置为对角顶点的一个矩形。
● 按下“c”键后,在窗体内单击鼠标左键,会显示以当前鼠标位置为圆心,以随机数为半径的一个圆。
● 按下“l”键后,在窗体内单击鼠标左键,会显示以当前鼠标位置为端点,以任意位置为另一个端点的线段。
● 按下“e”键后,在窗体内单击鼠标左键,会显示以当前鼠标位置为中心点,角度随机的一个椭圆。
● 按下“t”键后,在窗体内单击鼠标左键,会在当前窗体内显示颜色随机的文字“OpenCV”。此外,还通过“f”键和“u”键控制各种图形是否为实心:
● 按下“f”键后,图形为实心。
● 按下“u”键后,图形为空心。
如果要结束程序,可以按“Esc”键(ASCII码为27),此时程序退出循环,停止运行。
运行程序,按照上述控制方式绘制不同的对象,可以得到如下图所示的运行结果。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值