首页 > 技术文章 > 小白学pyhon(opencv鼠标操作)

mcl19909949541 2021-04-04 20:41 原文

opencv的鼠标交互操作主要通过两个函数实现:
第一个是cv2.setMouseCallback(windowName, onMouse [, param])
第二个是setMouseCallback()的第二个参数,称为鼠标回调函数onMouse(event, x, y, flags, param)

cv2.setMouseCallback(windowName, onMouse [, param])
第一个是你打开的窗口名字(要对应)
第二个是你定义的鼠标事件函数(任意)

鼠标回调函数:onMouse(event, x, y, flags, param)
这个参数列表不要改变它,除了param外其他都是由回调函数自动获取值。
1.event:由回调函数根据鼠标对图像的操作自动获得,内容包含左键点击,左键弹起,右键点击…等等等非常多的操作。
2. x,y:由回调函数自动获得,记录了鼠标当前位置的坐标,坐标以图像左上角为原点(0, 0),x方向向右为正,y方向向下为正。
3.flags:记录了一些专门的操作
4.param:从setMouseCallback()里传递过来的参数。该参数在setMouseCallback()处是可选参数,所以可以不设置。
param即为我们向里面传的图片参数
下面写一些简单的event

event:
EVENT_LBUTTONDBLCLK = 7         左键双击
EVENT_LBUTTONDOWN = 1           左键点击
EVENT_LBUTTONUP = 4             左键释放
EVENT_MBUTTONDBLCLK = 9         中间释放
EVENT_MBUTTONDOWN = 3           中间点击
EVENT_MBUTTONUP = 6             中间释放
EVENT_MOUSEHWHEEL = 11          滚轮事件
EVENT_MOUSEMOVE = 0             滑动
EVENT_MOUSEWHEEL = 10           滚轮事件
EVENT_RBUTTONDBLCLK = 8         右键双击
EVENT_RBUTTONDOWN = 2           右键点击
EVENT_RBUTTONUP = 5             右键释放


flags:
EVENT_FLAG_ALTKEY = 32          按Alt不放事件
EVENT_FLAG_CTRLKEY = 8          按Ctrl不放事件
EVENT_FLAG_LBUTTON = 1          左键拖拽
EVENT_FLAG_MBUTTON = 4          中键拖拽
EVENT_FLAG_RBUTTON = 2          右键拖拽
EVENT_FLAG_SHIFTKEY = 16        按Shift不放事件

下面写一个小例子:
在图像上用鼠标点击左键拖拽画一矩形,并输出矩形信息:

import cv2  as cv
import  numpy as np
def main():
    pitcurepath = "C:/Users/POG/Pictures/Autumn is coming WallPack/Timon Studler Mod.jpg"
    src = cv.imread(pitcurepath)
    cv.namedWindow("input image",cv.WINDOW_AUTOSIZE) #创建窗口
    cv.setMouseCallback("input image",draw_rectangle)
    while (1):
        cv.imshow('input image', src)
        if cv.waitKey(20) & 0xFF == 27:
            break


    cv.waitKey(0) #等待
    cv.destroyAllWindows() #销毁窗口

def draw_rectangle(event,x,y,flags,param):
    global ix, iy
    if event==cv.EVENT_LBUTTONDOWN:
        ix, iy = x, y
        print("point1:=", x, y)
    elif event==cv.EVENT_LBUTTONUP:
        print("point2:=", x, y)
        print("width=",x-ix)
        print("height=", y - iy)
        cv.rectangle(param, (ix, iy), (x, y), (0, 255, 0), 2)


if __name__ =="__main__":
    main()

在这里插入图片描述
1.鼠标点下显示位置,放开显示位置。
2.需要一个无限循环来刷新图像。
3.无限循环的退出条件由键盘获取,cv2.waitKey()用来获取键盘的按键,当我们点ESC后就可以退出。
but。。但我们往rectangle里传param发现并不能显示矩阵。。
那我们再写一个:

import cv2
def draw_rectangle(event,x,y,flags,param):
    global ix, iy
    if event==cv2.EVENT_LBUTTONDOWN:
        ix, iy = x, y
        print("point1:=", x, y)
    elif event==cv2.EVENT_LBUTTONUP:
        print("point2:=", x, y)
        print("width=",x-ix)
        print("height=", y - iy)
        cv2.rectangle(img, (ix, iy), (x, y), (0, 255, 0), 2)

img = cv2.imread("C:/Users/POG/Pictures/Autumn is coming WallPack/Timon Studler Mod.jpg")  #加载图片
cv2.namedWindow('image')
cv2.setMouseCallback('image', draw_rectangle)
while(1):
    cv2.imshow('image', img)
    if cv2.waitKey(20) & 0xFF == 27:
        break
cv2.destroyAllWindows()

在这里插入图片描述

这个img为全局变量就ok,我们可以知道往param传的参数若为自定义图片想要在图片上操作则必须要传全局变量。
则程序可写为:

import cv2  as cv
import  numpy as np
def main():
    pitcurepath = "C:/Users/POG/Pictures/Autumn is coming WallPack/Timon Studler Mod.jpg"
    global  src
    src = cv.imread(pitcurepath)
    cv.namedWindow("input image",cv.WINDOW_AUTOSIZE) #创建窗口
    cv.setMouseCallback("input image",draw_rectangle)
    while (1):
        cv.imshow('input image', src)
        if cv.waitKey(20) & 0xFF == 27:
            break


    cv.waitKey(0) #等待
    cv.destroyAllWindows() #销毁窗口

def draw_rectangle(event,x,y,flags,param):  #鼠标相应函数定义操作
    global ix, iy
    if event==cv.EVENT_LBUTTONDOWN:
        ix, iy = x, y
        print("point1:=", x, y)
    elif event==cv.EVENT_LBUTTONUP:
        print("point2:=", x, y)
        print("width=",x-ix)
        print("height=", y - iy)
        cv.rectangle(src, (ix, iy), (x, y), (0, 255, 0), 2)


if __name__ =="__main__":
    main()

在这里插入图片描述

注意 global 变量 必须要单独定义一行
则我们便可以进行一些有意思的操作了。
下面为画矩形区域,而且在区域内模糊(放到新图片里):

import cv2  as cv
import  numpy as np
def main():
    pitcurepath = "C:/Users/POG/Pictures/Autumn is coming WallPack/Timon Studler Mod.jpg"
    global  src
    src = cv.imread(pitcurepath)
    cv.namedWindow("input image",cv.WINDOW_AUTOSIZE) #创建窗口
    cv.setMouseCallback("input image",draw_rectangle)
    while (1):
        cv.imshow('input image', src)
        if cv.waitKey(20) & 0xFF == 27:
            break


    cv.waitKey(0) #等待
    cv.destroyAllWindows() #销毁窗口

def draw_rectangle(event,x,y,flags,param):  #鼠标相应函数定义操作
    global point1, point2
    if event==cv.EVENT_LBUTTONDOWN:
        point1 = (x,y)
        print("point1:=",point1[0],point1[1])
    elif event==cv.EVENT_LBUTTONUP:
        point2 = (x, y)
        print("point2:=", point2[0],point2[1])
        min_x = min(point1[0], point2[0])
        min_y = min(point1[1], point2[1])
        width = abs(point1[0] - point2[0])
        height = abs(point1[1] - point2[1])
        print("width=",width)
        print("height=", height)
        cv.rectangle(src, (point2[0],point2[1]), (point1[0],point1[1]), (0, 255, 0), 2)  #画矩形参数(图片,结束的位置,开始的位置,颜色,区域处理方式)

        cut_img = src[min_y:min_y+height, min_x:min_x+width]
        blur_demo( cut_img)

def blur_demo(image):#均值模糊

    dst = cv.blur(image,(10,30))# 前一个为水平方向模糊,后一个为竖直方向模糊
    cv.imshow("text",dst)

if __name__ =="__main__":
    main()

在这里插入图片描述
在这里插入图片描述
这里想了好久,因为截取的矩形区域只是画个框架,并不能对其进行操作(只是个矩形而以),然后我就像既然我知道矩形的位置坐标,就可以截取图片了呀,所以我就取巧截取图片并进行模糊处理的。(本来想的是模糊操作可以对图片局部进行模糊,发现竟然函数没有相应接口!?不得以就这样了)

推荐阅读