OpenCV for Python 学习 (二 事件与回调函数)

今天主要看了OpenCV中的事件以及回调函数,这么说可能不准确,主要是下面这两个函数(OpenCV中还有很多这些函数,可以在 http://docs.opencv.org/trunk/modules/highgui/doc/user_interface.html 找到,就不一一列举了),然后自己做了一个简单的绘图程序

函数如下:

cv2.setMouseCallback(windowName, onMouse[, param])
cv2.createTrackbar(trackbarName, windowName, value, count, onChange) 

先看第一个函数,cv2.setMouseCallback()

import cv2
import numpy as np

def draw_circle(event, x, y, flags, param):
    print type(param[0]), param[1]
    if event == cv2.EVENT_LBUTTONDBLCLK:
        cv2.circle(parma, (x,y), 100, (255,0,0), -1)

img = np.zeros((512,512,3), np.uint8)
a = []
cv2.namedWindow(‘image‘)
cv2.setMouseCallback(‘image‘, draw_circle, [img, a])

while(1):
    cv2.imshow(‘image‘,img)
    if cv2.waitKey(20) & 0xFF == 27:
        break
cv2.destroyAllWindows()

这段代码实现的功能是每当你在面板上双击时,绘制一个以双击点为园心,半径为100的圆

加粗的地方是设置回调函数的地方,共有3个参数,第一个参数,表示将要操作的面板名,第二个参数是回调函数名,第三个是给回调函数的参数

如果要给回调函数传递多个参数的话,则将这么多个参数存入一个列表/元组中,将其传入

然后看回调函数,共有5个参数:

第一个参数是鼠标事件名,可以通过如下方法查看OpenCV中的事件:

event = [i for i in dir(cv2) if ‘EVENT‘ in i]
print event

#############################################
EVENT_FLAG_ALTKEY   EVENT_FLAG_CTRLKEY
EVENT_FLAG_LBUTTON  EVENT_FLAG_MBUTTON
EVENT_FLAG_RBUTTON  EVENT_FLAG_SHIFTKEY
EVENT_LBUTTONDBLCLK  EVENT_LBUTTONDOWN
EVENT_LBUTTONUP     EVENT_MBUTTONDBLCLK
EVENT_MBUTTONDOWN   EVENT_MBUTTONUP
EVENT_MOUSEMOVE      EVENT_RBUTTONDBLCLK
EVENT_RBUTTONDOWN     EVENT_RBUTTONUP

这么多事件,基本看名字就能知道干么了,就不说了

第二个,第三个参数是鼠标在面板中的坐标

第四个参数是有没有其他特殊控制,比如在按左键的时候,按了Ctrl,Shift,Alt键等,参数也是刚刚上面的EVENT列表中的,通过事件名可以找到对应flags

第五个参数则是setMouseCallback()函数给回调函数传递的参数,至于怎么传递,前面已经说了(我的代码中,a没有用,只是为了演示如何给回调函数传递函数用的)

下面是第二个函数,cv2.createTrackbar()

共有5个参数,其实这五个参数看变量名就大概能知道是什么意思了

第一个参数,是这个trackbar对象的名字

第二个参数,是这个trackbar对象所在面板的名字

第三个参数,是这个trackbar的默认值

第四个参数,是这个trackbar上调节的范围(0~count)

第五个参数,是调节trackbar时调用的回调函数名(为什么此处没有像setMouseCallback函数一样,设置一个回调函数的参数项,这个还不清楚)

至于如何获取trackbar的当前位置,可以通过

cv2.getTrackbarPos(trackbarname, winname) 

这个函数获得当前trackbar的位置,这里的参数我就不解释了。

最后用这两个函数做了下面一个简单的绘图程序:

每次获取当前的色彩,鼠标按下后开始绘图,鼠标移动到哪,则画到哪,默认是绘制从起始点到终点的矩形,如果按了‘m‘键,则切换绘制以起始点和终点为直径的圆,圆心在两点的中心,如果再按‘m‘键,则切换会矩形。(由于本人对Python的变量作用域这块理解还不是很到位,因此用了很多全局变量,写的不好,请大家多多见谅)

import cv2
import numpy as np
import math
import copy as cp

drawing = False
mode = True
ix,iy = -1,-1
pre_img = np.zeros((512,512,3), np.uint8)
img = np.zeros((512,512,3), np.uint8)

def nothing(x):
    pass

def draw_circle(event, x, y, flags, param):
    global ix,iy,drawing,mode,pre_img,img

    # 每次获取当前Trackbar的位置
    r = cv2.getTrackbarPos(‘R‘, ‘hello‘)
    g = cv2.getTrackbarPos(‘G‘, ‘hello‘)
    b = cv2.getTrackbarPos(‘B‘, ‘hello‘)
    colors=(b,g,r)    

    print colors
    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        ix,iy = x,y
    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing == True:
            img = cp.deepcopy(pre_img)
            if mode == True:
                cv2.rectangle(img, (ix,iy), (x,y), colors, -1)
            else:
                length = int(math.sqrt((ix-x)**2+(iy-y)**2)/2)
                center = (int(float(ix+x)/2), int(float(iy+y)/2))
                cv2.circle(img, center, length, colors, -1)
    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        if mode == True:
            cv2.rectangle(img, (ix,iy), (x,y), colors,-1)
        else:
            length = int(math.sqrt((ix-x)**2+(iy-y)**2)/2)
            center = (int(float(ix+x)/2), int(float(iy+y)/2))
            cv2.circle(img, center, length, colors, -1)
        pre_img=img

# 创建面板
cv2.namedWindow(‘hello‘)

# 在面板‘hello‘上,创建3个trackbar,分别命名为R,G,B,回调函数都是啥都不做
cv2.createTrackbar(‘R‘, ‘hello‘, 0,255, nothing)
cv2.createTrackbar(‘G‘, ‘hello‘, 0,255, nothing)
cv2.createTrackbar(‘B‘, ‘hello‘, 0,255, nothing)

# 创建鼠标事件的回调函数
cv2.setMouseCallback(‘hello‘, draw_circle)

while(1):
    cv2.imshow(‘hello‘,img)
    k = cv2.waitKey(1) & 0xFF
    # 每次按‘m‘键都会切换状态,当m=True时,绘制矩形,m=False,绘制圆
    if k == ord(‘m‘):
        mode = not mode

    # 如果按了‘ESC‘键,则关闭面板
    elif k == 27:
        break

cv2.destroyAllWindows()

绘制出来的效果如下:

OpenCV for Python 学习 (二 事件与回调函数),布布扣,bubuko.com

时间: 2024-12-26 00:24:13

OpenCV for Python 学习 (二 事件与回调函数)的相关文章

OpenCV之Python学习笔记

OpenCV之Python学习笔记 直都在用Python+OpenCV做一些算法的原型.本来想留下发布一些文章的,可是整理一下就有点无奈了,都是写零散不成系统的小片段.现在看 到一本国外的新书<OpenCV Computer Vision with Python>,于是就看一遍,顺便把自己掌握的东西整合一下,写成学习笔记了.更需要的朋友参考. 阅读须知: 本文不是纯粹的译文,只是比较贴近原文的笔记:         请设法购买到出版社出版的书,支持正版. 从书名就能看出来本书是介绍在Pytho

[Python 学习] 二、在Linux平台上使用Python

这一节,主要介绍在Linux平台上如何使用Python 1. Python安装. 现在大部分的发行版本都是自带Python的,所以可以不用安装.如果要安装的话,可以使用对应的系统安装指令. Fedora系统:先以root登入,运行 yum install python Ubuntu系统:在root组的用户, 运行 sudo apt-get install python 2. 使用的Python的脚本 Linux是一个以文件为单位的系统,那么我们使用的Python是哪一个文件呢? 这个可以通过指令

OpenCV for Python 学习笔记 三

给源图像增加边界 cv2.copyMakeBorder(src,top, bottom, left, right ,borderType,value) src:源图像 top,bottem,left,right: 分别表示四个方向上边界的长度 borderType: 边界的类型 有以下几种: BORDER_REFLICATE # 直接用边界的颜色填充, aaaaaa | abcdefg | gggg BORDER_REFLECT # 倒映,abcdefg | gfedcbamn | nmabcd

OpenCV for Python 学习 (一 绘图函数)

本人的学习笔记主要记录的是学习opencv-python-tutorials这本书中的笔记 今天晚上简单学习OpenCV for Python如何绘图,主要用了这几个函数(这几个函数可在:http://docs.opencv.org/modules/core/doc/drawing_functions.html 找到): cv2.line(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) cv2.circle(img, center,

Python 3 进程池与回调函数

Python 3 进程池与回调函数 一.进程池 在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间.多进程是实现并发的手段之一,需要注意的问题是: 很明显需要并发执行的任务通常要远大于核数 一个操作系统不可能无限开启进程,通常有几个核就开几个进程 进程开启过多,效率反而会下降(开启进程是需要占用系统资源的,而且开启多余核数目的进程也无法做到并行) 例如当被操作对象数目不大时,可以直接利用multiprocessing中的Proces

python学习笔记11-python内置函数

python学习笔记11-python内置函数 一.查看python的函数介绍: https://docs.python.org/2/library/ 二.python内置函数 1.abs获取绝对值: 通过python官网查看abs abs(x) Return the absolute value of a number. The argument may be a plain or long integer or a floating point number. If the argument

详解C#委托,事件与回调函数

.Net编程中最经常用的元素,事件必然是其中之一.无论在ASP.NET还是WINFrom开发中,窗体加载(Load),绘制(Paint),初始化(Init)等等.“protected void Page_Load(object sender, EventArgs e)”这段代码相信没有人不熟悉的.细心一点一定会发现,非常多的事件方法都是带了“object sender, EventArgs e”这两个参数.这是不是和委托非常相似呢? 一.委托(有些书中也称为委派) 委托是什么呢?这个名字的意思已

学习C/C++之回调函数

1.函数指针 在学习回调函数之前,连了解下函数指针. (1)概念 指针是一个变量,用于表示内存的地址.在程序运行中,任何东西都要加载到内存,这就决定了任何东西都可以用指针指向. 函数是放在内存的代码区,它同样有地址,同样可以用指针来指向. (2)例子 //定义一个函数 void invoke(const char* s) { printf("%s\n", s); } void testFunctionPointer() { void (*fp)(const char* s); //声明

python通过multiprocessing 实现带回调函数的异步调用的代码

下边代码段是关于python通过multiprocessing 实现带回调函数的异步调用的代码. from multiprocessing import Pool def f(x): if __name__ == '__main__': pool = Pool(processes=1) # Start a worker processes. result = pool.apply_async(f, [10], callback) # Evaluate "f(10)" asynchron