Python Opencv 实现鼠标事件(包含一个练习)——事件触发讲解·以及鼠标回调函数的实现

文章目录

  • 鼠标事件概述
  • 鼠标事件发生的结构
    • 鼠标回调函数的标准格式
    • opencv下包含的所有事件——包含flag和event(可以看一下,熟悉常见事件范围)
    • 鼠标事件的实现函数
        • 一个完整的鼠标事件由一个自定义的鼠标回调函数+实现鼠标回调函数的设置
  • 实现一个鼠标事件
    • 第一步·创建自定义鼠标回调函数(记得调用库哦~)
    • 第二步·我们在__main__部分里,实现回调函数
    • 完整代码
    • 效果展示
  • 小案例——训练鼠标回调函数——以及多边形绘制
    • 要求
    • 思路
    • 代码实现
    • 效果展示

                         QQ:3020889729                                                                                 小蔡

鼠标事件概述

opencv可以实现gui拥有的功能——所以,opencv中也包含了鼠标事件——通过点击等等事件,执行相应的回调函数,实现指定的功能,最终实现交互!!!

鼠标事件发生的结构

鼠标回调函数的标准格式

鼠标回调函数的构造:函数名任意——但是参数应依次包含:event(事件),x, y,flags(标志),param(其它参数)
补充一下:事件和标志都可以作为事件触发的条件!!!

import cv2 as cv
import numpy as np

def mouse_circle(event, x, y, flags, param):  
	if event == cv.EVENT_LBUTTONDOWN:  # 该事件为鼠标左键按下
		pass  # 执行任务

opencv下包含的所有事件——包含flag和event(可以看一下,熟悉常见事件范围)

事件列表:

  • if event == cv.EVENT_LBUTTONDBLCLK: # 触发事件为左键双击
  • if event == cv.EVENT_LBUTTONDOWN: # 触发事件为左键按下时
  • if event == cv.EVENT_LBUTTONUP: # 触发事件为左键弹起时
  • if event == cv.EVENT_RBUTTONDBLCLK: # 触发事件为右键双击时
  • if event == cv.EVENT_RBUTTONDOWN: # 触发事件为右键按下时
  • if event == cv.EVENT_RBUTTONUP: # 触发事件为右键弹起时
  • if event == cv.EVENT_MBUTTONDBLCLK: # 触发事件为中键滚轮双击时
  • if event == cv.EVENT_MBUTTONDOWN: # 触发事件为中键滚轮按下时
  • if event == cv.EVENT_MBUTTONUP: # 触发事件为中键滚轮弹起时
  • if event == cv.EVENT_MOUSEWHEEL: # 触发事件为中键滚轮滚动时
  • if event == cv.EVENT_MOUSEMOVE: # 触发事件为鼠标移动时

标志列表:

  • if flags == cv.EVENT_FLAG_ALTKEY: # 触发标志为ALT键按下时
  • if flags == cv.EVENT_FLAG_CTRLKEY: # 触发标志为CTRL键按下时
  • if flags == cv.EVENT_FLAG_LBUTTON: # 触发标志为鼠标左键按下时
  • if flags == cv.EVENT_FLAG_MBUTTON: # 触发标志为鼠标中键滚轮按下时
  • if flags == cv.EVENT_FLAG_RBUTTON: # 触发标志为鼠标右键按下时
  • if flags == cv.EVENT_FLAG_SHIFTKEY: # 触发标志为SHIFT键按下时

鼠标事件的实现函数

由方法cv.setMouseCallback(‘imag’, mouse_circle) 实现鼠标事件!!!

import cv2 as cv
import numpy as np

cv.setMouseCallback('imag', mouse_circle) 
 # 第一个参数为窗体名称——指的是哪个窗体下执行
 # 第二个参数为鼠标回调函数的名称——传入函数名称,指的是传入整个函数声明,而不是直接执行函数

一个完整的鼠标事件由一个自定义的鼠标回调函数+实现鼠标回调函数的设置

实现一个鼠标事件

这里采用鼠标左键按下为事件触发的条件——所以我们就要设置一个自定义回调函数,里边包含当事件为左键按下时,我们画一个88*88的矩形~

第一步·创建自定义鼠标回调函数(记得调用库哦~)

我们这里用到event——事件参数,当然,你可以修改它的名字,但是呢,只要记住这个位置在后边回调函数实现时,传入的是事件就ok啦~

def mouse_circle(event, x, y, flags, param):
    if event == cv.EVENT_LBUTTONDOWN:  # 触发事件为左键按下时
        cv.rectangle(img, (x, y), (x+88, y+88), (174, 238, 238), -1)  # 画一个88*88的GhostWhite(颜色)矩形

第二步·我们在__main__部分里,实现回调函数

还是老规矩,既然是用opencv的gui——那么我们就需要先创建一张照片(图像),接着创建一个窗体——然后把后边涉及的相关窗体放在同一个窗体下!!!(回调函数的实现也是挂在同一个窗体下的哦,要一一对应)

if __name__ == "__main__":
    img = np.zeros((512, 512, 3), np.uint8)
    cv.namedWindow('imag', cv.WINDOW_NORMAL)  # 创建一个可改变大小的窗体
    cv.resizeWindow('imag', 510, 510)  # 大小设置
    cv.setMouseCallback('imag', mouse_circle)  # 实现鼠标回调函数到imag的窗体
    while True:
        cv.imshow('imag', img)
        k = cv.waitKey(10) & 0xFF  # 读取按键
        if k == ord('q') or k == ord('Q'):  # 结束绘制
            break
    cv.destroyAllWindows()

完整代码

import cv2 as cv
import numpy as np


# 该回调函数用来花矩形
def mouse_circle(event, x, y, flags, param):
    if event == cv.EVENT_LBUTTONDOWN:  # 触发事件为左键按下时
        cv.rectangle(img, (x, y), (x+88, y+88), (174, 238, 238), -1)  # 画一个88*88的GhostWhite(颜色)矩形


if __name__ == "__main__":
    img = np.zeros((512, 512, 3), np.uint8)
    cv.namedWindow('imag', cv.WINDOW_NORMAL)
    cv.resizeWindow('imag', 510, 510)
    cv.setMouseCallback('imag', mouse_circle) 
    while True:
        cv.imshow('imag', img)
        k = cv.waitKey(10) & 0xFF
        if k == ord('q') or k == ord('Q'):
            break
    cv.destroyAllWindows()

效果展示

点击一次——按下时就产生图形了~
Python Opencv 实现鼠标事件(包含一个练习)——事件触发讲解·以及鼠标回调函数的实现_第1张图片
多次按下就有多个图形
Python Opencv 实现鼠标事件(包含一个练习)——事件触发讲解·以及鼠标回调函数的实现_第2张图片
我们可以用鼠标点击,用矩形拼凑一个小图形出来~说明,我们实现的事件,是画到了图片上并且保留到图片上了的
Python Opencv 实现鼠标事件(包含一个练习)——事件触发讲解·以及鼠标回调函数的实现_第3张图片

小案例——训练鼠标回调函数——以及多边形绘制

要求

  1. 在一个回调函数中,实现每一次鼠标点击,产生一个三角形
  2. 并且,要求,当m按键按下后,三角形倒置!!!
  3. 并且规定ESC键按下时,退出opencv的界面(也就是破出显示的条件)

思路

  1. 按键部分:
  2. 既然要求按键按下要绘制不同的图形,那么,我们就设置一个全局变量mode_up_down=True,当为True时,正常绘图,否则倒置绘图~
  3. 这就要用到我们cv.waitKey(10)获取按键,然后判断是否是m键,是就翻转mode_up_down的值——mode_up_down = ~mode_up_down
  4. 至于退出界面,我们也通过这个办法获取ESC按键!!!
  5. 绘制部分:
  6. 至于绘制三角形只需要使用polylines来实现多边形绘制(至于倒置三角形:就是将底边顶点的y值与上顶点的y值互换!)可前往另一篇博客查看polylines的多边形绘制
  7. 回调函数部分:——代码中去讲解可能会好些~

代码实现

import cv2 as cv
import numpy as np

drawing = False  # True时,才绘图
mode_up_down = True  # 为true时,实现等腰三角形正向图;Flase时,实现倒图
ix, iy = -1, -1  # 为画图(上顶点)坐标_采用全局变量获取实时坐标

# 我们引入全局变量,实现绘制的控制
def mouse_function(event, x, y, flags, param):
    global drawing, mode_up_down, mode_color, ix, iy
    if event == cv.EVENT_LBUTTONDOWN:  # 鼠标左键按下,允许绘图,以及获取绘图坐标
        drawing = True  # 允许绘图
        ix, iy = x, y  # 获取坐标
    elif event == cv.EVENT_LBUTTONUP:  # 弹起时就绘制图形
        drawing = False  # 关闭绘制功能
        if mode_up_down:
            pst = np.array([[ix, iy], [ix - 30, iy + 30], [ix + 30, iy + 30]], np.int32)  # 为多边形绘制的顶点配置
            pst = pst.reshape((3, 1, 2))
            cv.polylines(img, [pst], True, (0, 0, 255), 2, cv.LINE_AA)
        else:  # 绘制倒置图形
            pst = np.array([[ix - 30, iy], [ix + 30, iy], [ix, iy + 30]], np.int32)  # 倒置顶点的配置
            pst = pst.reshape((3, 1, 2))
            cv.polylines(img, [pst], True, (0, 0, 255), 2, cv.LINE_AA)
    elif event == cv.EVENT_MOUSEMOVE:  # 按键未弹起,移动位置之后也发生绘图
        if drawing == True:
            if mode_up_down:
                pst = np.array([[ix, iy], [ix - 30, iy + 30], [ix + 30, iy + 30]], np.int32)
                pst = pst.reshape((3, 1, 2))
                cv.polylines(img, [pst], True, (0, 0, 255), 2, cv.LINE_AA)
            else:
                pst = np.array([[ix - 30, iy], [ix + 30, iy], [ix, iy + 30]], np.int32)
                pst = pst.reshape((3, 1, 2))
                cv.polylines(img, [pst], True, (0, 0, 255), 2, cv.LINE_AA)


if __name__ == "__main__":
    img = np.zeros((512, 512, 3), np.uint8)
    cv.namedWindow('imag', cv.WINDOW_NORMAL)
    cv.resizeWindow('imag', 510, 510)
    cv.setMouseCallback('imag', mouse_function)  # 实现鼠标回调函数

    while True:
        cv.imshow('imag', img)
        k = cv.waitKey(10) & 0xFF
        if k == 27:
            break
        elif k == ord('m') or k == ord('M'):
            mode_up_down = not mode_up_down
    cv.destroyAllWindows()

效果展示

默认绘制正图形,按下m键就翻转——正反,反正的变化规则~
Python Opencv 实现鼠标事件(包含一个练习)——事件触发讲解·以及鼠标回调函数的实现_第4张图片

你可能感兴趣的:(#,Opencv学习笔记,opencv,python,numpy,计算机视觉)