☞ ░ 前往老猿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’。在实现上述代码时有几点需要注意:

  1. fps设置要小,否则后面的帧在屏幕上覆盖了前面加了字符的帧图像,无法看清字符;
  2. setMouseCallback 必须在每次读到新帧后设置,否则回调函数中收到的参数param就不是指向当前帧,而是调用回调函数时frame变量对应帧,有可能frame还没定义或者定义的初始值如None,这样后面的鼠标点击无法触发对当前帧的操作;
  3. setMouseCallback调用时必须在窗口已经通过cv2.namedWindow或cv2.imshow定义了窗口名字之后,否则窗口没有定义回调函数设置没有作用;
  4. 回调函数对当前帧添加了字符之后,需要再次调用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的传递方法解析的更多相关文章

  1. 第5.4节 Python函数中的变量及作用域

    一.函数中的变量使用规则 函数执行时,使用的全局空间是调用方的全局空间,参数及函数使用的局部变量存储在函数单独的局部名字空间内: 函数的形参在函数中修改了值时,并不影响调用方本身的数据,但如果形参是一 ...

  2. 使用匿名函数在回调函数中正确访问JS循环变量

    有时候, 需要以不同的参数调用某个URL,并且在回调函数中仍然可以访问正在使用的参数, 这时候, 需要使用闭包保存当前参数, 否则, 当回调函数执行时, 之前的参数很可能早已被修改为最后一个参数了. ...

  3. 回调函数中使用MFC类的成员或对话框控件的简单方法

    在MFC的很多程序中,常常需要在回调函数中调用MFC类的类成员变量.类成员函数,亦或者对话框控件的句柄.由于回调函数是基于C编程的Windows SDK的技术,而类成员又有this指针客观条件限制.. ...

  4. JavaScript 回调函数中的 return false 问题

    今天一个同事问了我一个问题,就是在 Ajax 方法中,请求成功后(success)的回调函数中根据响应的值来判断程序是否继续执行,他不解的是在回调函数中已经 return false 了,但是 Aja ...

  5. Javascript回调函数中的this指向问题

    使用js中的定时器(setInterval,setTimeout),很容易会遇到this指向的问题. 直接上例子: 1 var name = 'my name is window'; 2 var ob ...

  6. django变量使用-在模板中使用视图函数中的变量

    DTL语言,即django template language 第一次使用时,需要修改项目的setting.py文件,将其中TEMPLATES中的DIRS修改为os.path.join(BASE_DI ...

  7. vue中this在回调函数中的使用

    this在各类回调中使用: 如果是普通函数是没法使用的 所以需要先将this.变量赋值给新的变量,然后才能在回调函数中使用 例如: refund: function (id) { if (!this. ...

  8. 【spring 后台跳转前台】使用ajax访问的后台,后台正常执行,返回数据,但是不能进入前台的ajax回调函数中

    问题: 使用ajax访问的后台,后台正常执行,并且正常返回数据,但是不能进入前台的ajax回调函数中 问题展示:  问题解决: 最后发现是因为后台的方法并未加注解:@ResponseBody,导致方法 ...

  9. JS回调函数中的this指向(详细)

    首先先说下正常的this指向问题 什么是this:自动引用正在调用当前方法的.前的对象. this指向的三种情况 1. obj.fun()     fun中的this->obj,自动指向.前的对 ...

随机推荐

  1. python3 文件增删查

    #Author by Andy#_*_ coding:utf-8 _*_import sysimport timePath="E:\my python study\\files\haprox ...

  2. Linux 浅谈Linux 操作系统的安全设置

    如今linux系统安全变的越来越重要了,这里我想把我平时比较常使用的一些linux下的基本的安全措施写出来和大家探讨一下,让我们的linux系统变得可靠. 1.BIOS的安全设置 这是最基本的了,也是 ...

  3. spark streaming中使用checkpoint

    从官方的Programming Guides中看到的 我理解streaming中的checkpoint有两种,一种指的是metadata的checkpoint,用于恢复你的streaming:一种是r ...

  4. C#中如何利用操作符重载和转换操作符

    操作符重载 有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成 ...

  5. apk反编译(8)如何完全防止反编译?

    在android 的应用很难做到完全防止反编译,即使用ProGuard混淆的后,也能得到smali代码,这个语法也很简单,很容易理解. 只能通过增加破解难度和成本,使破解者失去耐心. 其中一个常见解决 ...

  6. ResourceBundle

    ResourceBundle本质上也是一个映射,但是它提供了国际化的功能.  假设电脑设置的地区是中国大陆,语言是中文  那么你向ResourceBundle(资源约束名称为base)获取abc变量的 ...

  7. golang 栈操作

    Monk's Love for Food   Our monk loves food. Hence,he took up position of a manager at Sagar,a restau ...

  8. 蒙特卡洛树,AMAF,Rave浅析

    蒙特卡洛树搜索: MCTS使用蒙特卡洛模拟来估计每个节点的价值. 其默认策略为贪婪算法, 即每次选择价值最高的节点进行模拟, 在每次模拟得到结果后, 将结果反馈回每个上级节点, 更新节点价值. 通常来 ...

  9. BIT-区间修改单点查询

    正好刷题时碰到了这个之前遇到过的问题,类似的还有区间修改区间查询,以后学了会补上. 我们知道BIT只支持单点修改区间查询,如果现在问题变成每次让一个区间的数同时变化,然后询问的是某一个点得值的时候该怎 ...

  10. Go程序语言设计 (艾伦 A. A. 多诺万 著)

    第1章 入门  (已看) 1.1 hello,world package main import "fmt" func main(){ fmt.Println("Hell ...