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