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,自动指向.前的对 ...
随机推荐
- JQuery cdn地址
国外的CDN: 1.Google Hosted Libraries src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery ...
- yum安装出现被锁定的报错
问题:在使用#yum install XXX 命令的时候,出现yum.pid 已被锁定的提示,无法进行yum 安装 解决: 使用# rm -f /var/run/yum.pid 命令删除该进程即可
- 5、Python语法之基本数据类型
一 引入 我们学习变量是为了让计算机能够像人一样去记忆事物的某种状态,而变量的值就是用来存储事物状态的,很明显事物的状态分成不同种类的(比如人的年龄,身高,职位,工资等等),所以变量值也应该有不同的类 ...
- 记一次使用idea插件CamelCase技巧
1.在idea中下载插件CamelCase插件 2.使用Shift+Alt+U快捷键进行转换 3.由于转换格式比较导致多次使用快捷键才能达到自己想要的效果,此插件提供了允许禁用某些转换或更改它们在首 ...
- 如何让Visual Studio 2019更好用(VS2019配置指南)
今天电脑没带,借用外面的电脑配环境来用.刚下载完的VS是这样的: UI挺好看的,但代码窗口看起来就和上个世纪的VC6没什么区别,快捷键用起来也不顺手.(2333) 接下来,我们将一步步优化编写环境,让 ...
- StringUtil字符串工具-功能扩展
对java的String类的一些小补充. public class StringUtil { /** 将一个字符串的首字母大写然后返回. @param str 要处理的目标字符串. @return S ...
- Mockserver之Moco框架搭建使用
客户要求进行完整的产品展示,人员和时间都有限,来不及开发后端服务... 工期比较紧的项目,前端已开发完成,需要调试,后端接口还未开发完成... 公司某个项目依赖于第三方服务,但是第三方服务不方便频繁调 ...
- quic 分析 1
问题1:quic握手过程是怎样的? 怎样节约握手时间?握手时间多少个RTT?握手过程成涉及到哪些概念以及变量(代码) 0~1 RTT握手过程 QUIC握手的过程是需要一次数据交互,0-RTT时延即 ...
- tcpdump详解(转)
tcpdump是Linux下强大的抓包工具,不仅可以分析数据包流向,还可以对数据包内容进行监听.通过分析数据包流向,可以了解一条连接是如何建立双向连接的.tcpdump允许用户(一般是root)拦截和 ...
- Linux mysql 修改密码 三种方式(转载)
注明:本文为转载,原文地址:https://www.cnblogs.com/chuckjam/archive/2018/08/10/9456255.html 前言 有时我们会忘记Mysql的密码,或者 ...