OpenCV-Python setMouseCallback回调函数中图像变量img的传递方法解析
☞ ░ 前往老猿Python博文目录 ░
一、使用全局变量进行变量传递
OpenCV-Python中可以使用setMouseCallback来设置鼠标事件的回调函数,我们来看个样例。
1.1、案例1代码
import numpy as np
import cv2 #freetype
mode = 0
#创建回调函数
def OnMouseAction(event,x,y,flags,param):
global x1, y1
img = img1
if mode == 0 and event == cv2.EVENT_LBUTTONDOWN:
print("左键点击")
cv2.line(img,(0,0),(x,y),(255,255,0),2)
if mode == 1 and event == cv2.EVENT_LBUTTONDOWN:
print("左键点击1")
x1, y1 = x, y
elif mode == 1 and event==cv2.EVENT_MOUSEMOVE and flags ==cv2.EVENT_FLAG_LBUTTON:
print("左鍵拖曳1")
cv2.rectangle(img2,(x1,y1),(x,y),(0,255,0),-1)
img1 = np.zeros((500,500,3),np.uint8)
img2= np.zeros((500,500,3),np.uint8)
cv2.putText(img1,'1',(200,200),cv2.FONT_HERSHEY_SIMPLEX, 4, (255,0,0))
cv2.putText(img2,'2',(200,200),cv2.FONT_HERSHEY_SIMPLEX, 4, (255,0,0))
cv2.namedWindow('image1')
cv2.namedWindow('image2')
cv2.setMouseCallback('image1',OnMouseAction)
while(1):
cv2.imshow('image1',img1)
cv2.imshow('image2', img2)
cbf()
k=cv2.waitKey(1)
if k==ord('l'):
mode = 0
elif k==ord('t'):
mode = 1
elif k==ord('q'):
break
cv2.destroyAllWindows()
1.2、案例1程序功能及运行截图
上面的代码创建了两个图像窗口,在窗口image1中设置了回调函数,当开始运行时,直接在窗口1中画线,当输入‘t’键切换模式后,在窗口中的拖拽却在窗口2中画填充的矩形。运行截图:
1.3、简析
回调函数OnMouseAction中使用了两个全局变量img1、img2,因此回调函数中对图像的操作是通过全局变量来实现的。关于该使用方法请参考《第5.4节 Python函数中的变量及作用域》的介绍。
二、使用回调函数参数param进行变量传递
当回调函数要操作的对象不是全局变量时,回调函数就不能使用第一种方法传递变量,此时只能通过回调函数参数param进行变量传递。
2.1、案例2:将案例1中的img1传值改成param进行传递
import numpy as np
import cv2 #freetype
mode = 0
#创建回调函数
def OnMouseAction(event,x,y,flags,param):
global x1, y1
img = param
if mode == 0 and event == cv2.EVENT_LBUTTONDOWN:
print("左键点击")
cv2.line(img,(0,0),(x,y),(255,255,0),2)
if mode == 1 and event == cv2.EVENT_LBUTTONDOWN:
print("左键点击1")
x1, y1 = x, y
elif mode == 1 and event==cv2.EVENT_MOUSEMOVE and flags ==cv2.EVENT_FLAG_LBUTTON:
print("左鍵拖曳1")
cv2.rectangle(img2,(x1,y1),(x,y),(0,255,0),-1)
img1 = np.zeros((500,500,3),np.uint8)
img2= np.zeros((500,500,3),np.uint8)
cv2.putText(img1,'1',(200,200),cv2.FONT_HERSHEY_SIMPLEX, 4, (255,0,0))
cv2.putText(img2,'2',(200,200),cv2.FONT_HERSHEY_SIMPLEX, 4, (255,0,0))
cv2.namedWindow('image1')
cv2.namedWindow('image2')
cv2.setMouseCallback('image1',OnMouseAction,img1)
while(1):
cv2.imshow('image1',img1)
cv2.imshow('image2', img2)
k=cv2.waitKey(1)
if k==ord('l'):
mode = 0
elif k==ord('t'):
mode = 1
elif k==ord('q'):
break
cv2.destroyAllWindows()
上面的代码和案例1的代码相比,只修改了第11行和32行的代码,但程序功能完全相同,这证明了param传值的可行性。
2.2、案例3
# -*- coding: utf-8 -*-
import cv2
def OnMouseLBUTTONDOWN(event,x,y,flags,param):
frame = param
if frame is not None:
if event == cv2.EVENT_LBUTTONDOWN:
cv2.putText(frame,'Mouse left button Pressed',(x,y), cv2.FONT_HERSHEY_SIMPLEX,1, (255,0,0))
cv2.imshow('video', frame)
else:
print("frame is None")
def playVideoFile():
cap = cv2.VideoCapture(r'f:\video\zbl1.mp4')
fps = 1
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
# 逐帧捕获
ret, frame = cap.read()
if not ret:
if frame is None :
print("The video has end.")
else:
print("Read video error!")
break
# 显示结果帧e
cv2.imshow('video', frame)
cv2.setMouseCallback('video', OnMouseLBUTTONDOWN, frame)
if cv2.waitKey(int(1000/fps)) == ord('q'): break
# 完成所有操作后,释放捕获器
cap.release()
cv2.destroyAllWindows()
playVideoFile()
上面的代码读取某个视频文件逐帧显示,并在显示后设置回调函数,回调函数就是当鼠标按下时,在当前帧图片上鼠标按下位置显示’Mouse left button Pressed’。在实现上述代码时有几点需要注意:
- fps设置要小,否则后面的帧在屏幕上覆盖了前面加了字符的帧图像,无法看清字符;
- setMouseCallback 必须在每次读到新帧后设置,否则回调函数中收到的参数param就不是指向当前帧,而是调用回调函数时frame变量对应帧,有可能frame还没定义或者定义的初始值如None,这样后面的鼠标点击无法触发对当前帧的操作;
- setMouseCallback调用时必须在窗口已经通过cv2.namedWindow或cv2.imshow定义了窗口名字之后,否则窗口没有定义回调函数设置没有作用;
- 回调函数对当前帧添加了字符之后,需要再次调用cv2.imshow该帧才会刷新显示。
更多OpenCV-Python的介绍请参考《OpenCV-Python图形图像处理》。
关于老猿的付费专栏
老猿的付费专栏《使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,付费专栏《moviepy音视频开发专栏》详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,两个专栏加起来只需要19.9元,都适合有一定Python基础但无相关专利知识的小白读者学习。
收费专栏文章目录:《moviepy音视频开发专栏文章目录》、《使用PyQt开发图形界面Python应用专栏目录》。
对于缺乏Python基础的同仁,可以通过老猿的免费专栏《专栏:Python基础教程目录》从零开始学习Python。
如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。
跟老猿学Python、学OpenCV!
☞ ░ 前往老猿Python博文目录 ░
OpenCV-Python setMouseCallback回调函数中图像变量img的传递方法解析的更多相关文章
- 第5.4节 Python函数中的变量及作用域
一.函数中的变量使用规则 函数执行时,使用的全局空间是调用方的全局空间,参数及函数使用的局部变量存储在函数单独的局部名字空间内: 函数的形参在函数中修改了值时,并不影响调用方本身的数据,但如果形参是一 ...
- 使用匿名函数在回调函数中正确访问JS循环变量
有时候, 需要以不同的参数调用某个URL,并且在回调函数中仍然可以访问正在使用的参数, 这时候, 需要使用闭包保存当前参数, 否则, 当回调函数执行时, 之前的参数很可能早已被修改为最后一个参数了. ...
- 回调函数中使用MFC类的成员或对话框控件的简单方法
在MFC的很多程序中,常常需要在回调函数中调用MFC类的类成员变量.类成员函数,亦或者对话框控件的句柄.由于回调函数是基于C编程的Windows SDK的技术,而类成员又有this指针客观条件限制.. ...
- JavaScript 回调函数中的 return false 问题
今天一个同事问了我一个问题,就是在 Ajax 方法中,请求成功后(success)的回调函数中根据响应的值来判断程序是否继续执行,他不解的是在回调函数中已经 return false 了,但是 Aja ...
- Javascript回调函数中的this指向问题
使用js中的定时器(setInterval,setTimeout),很容易会遇到this指向的问题. 直接上例子: 1 var name = 'my name is window'; 2 var ob ...
- django变量使用-在模板中使用视图函数中的变量
DTL语言,即django template language 第一次使用时,需要修改项目的setting.py文件,将其中TEMPLATES中的DIRS修改为os.path.join(BASE_DI ...
- vue中this在回调函数中的使用
this在各类回调中使用: 如果是普通函数是没法使用的 所以需要先将this.变量赋值给新的变量,然后才能在回调函数中使用 例如: refund: function (id) { if (!this. ...
- 【spring 后台跳转前台】使用ajax访问的后台,后台正常执行,返回数据,但是不能进入前台的ajax回调函数中
问题: 使用ajax访问的后台,后台正常执行,并且正常返回数据,但是不能进入前台的ajax回调函数中 问题展示: 问题解决: 最后发现是因为后台的方法并未加注解:@ResponseBody,导致方法 ...
- JS回调函数中的this指向(详细)
首先先说下正常的this指向问题 什么是this:自动引用正在调用当前方法的.前的对象. this指向的三种情况 1. obj.fun() fun中的this->obj,自动指向.前的对 ...
随机推荐
- 【Spring Boot】web开发
springboot在开发web项目的时候具备天然的优势,现在的很多企业级开发都是依托于springboot的. 使用springboot的步骤: 1.创建一个SpringBoot应用,选 ...
- Azure Data Factory(四)集成 Logic App 的邮件通知提醒
一,引言 上一篇有介绍到使用Azure Data Factory 复制数据,然后有集成 Azure DevOps 实现CI/CD,但是对于真正的项目来说,这些肯定是不够的,比如说在执行 Azure P ...
- JS缓冲运动案例:右侧居中悬浮窗
JS缓冲运动案例:右侧居中悬浮窗 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta cha ...
- martini-能量最小化参数(mdp文件)
1 ; 2 ; STANDARD MD INPUT OPTIONS FOR MARTINI 2.x 3 ; Updated 02 feb 2013 by DdJ 4 ; 5 ; for use wit ...
- 微信公众号Makrdown编辑器,语法你懂吗?
感谢 WeChat Format 源码: https://github.com/lyricat/wechat-format! 其他工具推荐: 微信公众号编辑器 Makrdown: https://md ...
- Fiddler中添加serverIP
以前一直觉得chrome浏览器中能看到remoteIP,真是觉得太酷了!一直想要fiddler也拥有这种技能,有天好奇的在网上搜了一下,真的可以,改造下fiddler脚本即可:上面那句是算接口请求的t ...
- samba配置用户访问方法
配置目的: 为了给指定用户一个独立访问目录 首先在samba服务器安装samba软件 $ apt-get install samba 然后配置独立访问用户 配置samba用户前提需要是linux的用户 ...
- Javaer 进阶必看的 RocketMQ ,就这篇了
每个时代,都不会亏待会学习的人. 大家好,我是 yes. 继上一篇 头条终面:写个消息中间件 ,我提到实现消息中间件的一些关键点,今天就和大家一起深入生产级别消息中间件 - RocketMQ 的内核实 ...
- 可以把思维导图导出为word文档方便其他人查看吗?
MindManager除了强大的大纲视图编辑功能外,还拥有多种导出格式,方便大家迅速导出文件,在团队中分享自己的观点,提高团队的工作效率,本次小编使用的思维导图软件版本是MindManager 202 ...
- python 如何跳过异常继续执行
使用try...except...语句,类似于if...else...,可以跳过异常继续执行程序,这是Python的优势 用法如下: 1 2 3 4 5 6 try: # 可能会 ...