美文网首页
OpenCV_005-OpenCV 鼠标作为画笔

OpenCV_005-OpenCV 鼠标作为画笔

作者: hanpfei | 来源:发表于2022-03-20 14:37 被阅读0次

    本文主要内容来自于 OpenCV-Python 教程OpenCV 中的 GUI 功能 部分,这个部分的主要内容如下:

    目标

    简单的演示程序

    这里,我们将创建一个简单的应用程序,当双击鼠标左键时,它在一幅图像上绘制一个圆。

    首先我们创建一个鼠标事件回调函数,当鼠标事件发生时它将被执行。鼠标事件可以是任何与鼠标相关的事件,比如左键按下,左键抬起,左键双击等等。它给我们每个鼠标事件的坐标 (x,y)。通过这个事件和位置,我们可以做任何我们想做的。要列出所有可用的事件,可以在 Python 终端中执行如下的代码:

    events = [i for i in dir(cv) if 'EVENT' in i]
    print('\n'.join(events))
    

    执行这段代码将得到类似下面这样的输出:

    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_MOUSEHWHEEL
    EVENT_MOUSEMOVE
    EVENT_MOUSEWHEEL
    EVENT_RBUTTONDBLCLK
    EVENT_RBUTTONDOWN
    EVENT_RBUTTONUP
    

    创建鼠标事件回调函数具有特定的格式,在任何地方都是相同的。它们仅在函数做什么方面不同。即鼠标事件回调函数可以是参数列表满足条件的任何函数。我们的鼠标事件回调函数只做一件事,它在双击发生的位置绘制一个圆。参见下面的代码。代码是自解释的:

    def draw_circle_follow_mouse():
        img = np.zeros((512, 512, 3), np.uint8)
    
        # mouse callback function
        def draw_circle(event, x, y, flags, param):
            if event == cv.EVENT_LBUTTONDBLCLK:
                # Create a black image, a window and bind the function to window
                img.fill(0)
                cv.circle(img, (x, y), 100, (255, 0, 0), -1)
                cv.imshow('image', img)
    
        cv.namedWindow('image')
        cv.imshow('image', img)
        cv.setMouseCallback('image', draw_circle)
        while (1):
            if cv.waitKey(20) & 0xFF == 27:
                break
        cv.destroyAllWindows()
    

    这里的鼠标事件回调函数其实是个闭包,它绑定了局部上下文。为了防止两次鼠标双击事件中的绘制相互干扰,每次在鼠标事件回调函数中绘制之前都会先清空图像。ASCII 码 27 表示 ESC 键,即按下 ESC 键是应用程序退出。

    更高级的演示程序

    现在我们继续开发一个更好的应用程序。这次,我们像在 Paint 应用程序中一样,通过拖动鼠标绘制矩形或者圆(依赖我们选择的模式)。因此我们的鼠标事件回调函数有两部分,一部分用于绘制矩形,另一部分用于绘制圆形。这个具体的例子将非常有助于创建和理解一些交互式应用程序,如对象跟踪、图像分割等。

    def draw_shape_follow_mouse():
        drawing = False  # true if mouse is pressed
        mode = True  # if True, draw rectangle. Press 'm' to toggle to curve
        ix, iy = -1, -1
    
        img = np.zeros((512, 512, 3), np.uint8)
        # mouse callback function
        def draw_shape(event, x, y, flags, param):
            nonlocal ix, iy, drawing, mode
            if event == cv.EVENT_LBUTTONDOWN:
                drawing = True
                ix, iy = x, y
                img.fill(0)
            elif event == cv.EVENT_MOUSEMOVE:
                if drawing == True:
                    if mode == True:
                        cv.rectangle(img, (ix, iy), (x, y), (0, 255, 0), -1)
                    else:
                        cv.circle(img, (x, y), 5, (0, 0, 255), -1)
            elif event == cv.EVENT_LBUTTONUP:
                drawing = False
                if mode == True:
                    cv.rectangle(img, (ix, iy), (x, y), (0, 255, 0), -1)
                else:
                    cv.circle(img, (x, y), 5, (0, 0, 255), -1)
    
            cv.imshow('image', img)
    
        cv.namedWindow('image')
        cv.imshow('image', img)
        cv.setMouseCallback('image', draw_shape)
        while (1):
            key = cv.waitKey(20) & 0xFF
            if key == ord('m'):
                mode = not mode
            elif key == 27:
                break
        cv.setMouseCallback(None)
        cv.destroyAllWindows()
    

    这里的鼠标事件回调函数同样是闭包,通过 cv.setMouseCallback() 将回调函数绑定到 OpenCV 窗口。在主循环中,我们应该为键 'm' 设置一个键盘绑定,以在矩形和圆形之间切换。

    参考文档

    Mouse as a Paint-Brush

    Done.

    相关文章

      网友评论

          本文标题:OpenCV_005-OpenCV 鼠标作为画笔

          本文链接:https://www.haomeiwen.com/subject/ihnodrtx.html