Mouse as a Paint-Brush - 鼠标作为画笔

Mouse as a Paint-Brush - 鼠标作为画笔

OpenCV documentation index - OpenCV 文档索引
https://www.docs.opencv.org/

master (4.x)
https://www.docs.opencv.org/master/

3.4 (3.4.x)
https://www.docs.opencv.org/3.4/

2.4 (2.4.x)
https://www.docs.opencv.org/2.4/

1. Mouse as a Paint-Brush

3.4 (3.4.x) -> OpenCV-Python Tutorials -> Gui Features in OpenCV -> Mouse as a Paint-Brush

Here you will learn how to display and save images and videos, control mouse events and create trackbar.
在这里您将学习如何显示和保存图像和视频,控制鼠标事件和创建轨迹栏。

Draw stuffs with your mouse.
用鼠标画东西。

paint brush:漆刷,涂漆刷,油漆刷
brush [brʌʃ]:n. 刷子,画笔,毛笔,争吵,与某人有效冲突,灌木丛地带,矮树丛,狐狸尾巴 vt. 刷,画 vi. 刷,擦过,掠过,(经过时) 轻触

2. Goal

Learn to handle mouse events in OpenCV
You will learn these functions : cv.setMouseCallback()

3. Simple Demo

Here, we create a simple application which draws a circle on an image wherever we double-click on it.
在这里,我们创建了一个简单的应用程序,无论我们在哪里双击它,都会在图像上绘制一个圆圈。

First we create a mouse callback function which is executed when a mouse event take place. Mouse event can be anything related to mouse like left-button down, left-button up, left-button double-click etc. It gives us the coordinates (x,y) for every mouse event. With this event and location, we can do whatever we like. To list all available events available, run the following code in Python terminal:
首先,我们创建一个鼠标回调函数,该函数在鼠标事件发生时执行。鼠标事件可以是与鼠标相关的任何内容,如左键向下,左键向上,左键双击等。它为我们提供了每个鼠标事件的坐标 (x,y)。 通过此活动和地点,我们可以做任何我们喜欢的事情。要列出所有可用的可用事件,请在 Python 终端中运行以下代码:

import cv2 as cv
events = [i for i in dir(cv) if 'EVENT' in i]
print( events )
#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
cv.setMouseCallback()
To list all available events available, run the following code in Python terminal.
"""

import cv2 as cv

events = [i for i in dir(cv) if 'EVENT' in i]
print(events)
/usr/bin/python3.5

['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']

Process finished with exit code 0

Creating mouse callback function has a specific format which is same everywhere. It differs only in what the function does. So our mouse callback function does one thing, it draws a circle where we double-click. So see the code below. Code is self-explanatory from comments :
创建鼠标回调函数具有特定的格式,在任何地方都是相同的。它仅在功能方面有所不同。所以我们的鼠标回调函数做了一件事,它绘制了一个双击的圆圈。所以请看下面的代码。

import numpy as np
import cv2 as cv
# mouse callback function
def draw_circle(event,x,y,flags,param):
    if event == cv.EVENT_LBUTTONDBLCLK:
        cv.circle(img,(x,y),100,(255,0,0),-1)
# Create a black image, a window and bind the function to window
img = np.zeros((512,512,3), np.uint8)
cv.namedWindow('image')
cv.setMouseCallback('image',draw_circle)
while(1):
    cv.imshow('image',img)
    if cv.waitKey(20) & 0xFF == 27:
        break
cv.destroyAllWindows()
#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
cv.setMouseCallback()
Creating mouse callback function has a specific format which is same everywhere.
It differs only in what the function does.
So our mouse callback function does one thing, it draws a circle where we double-click.
"""

import numpy as np
import cv2 as cv


# mouse callback function
def draw_circle(event, x, y, flags, param):
    if event == cv.EVENT_LBUTTONDBLCLK:
        cv.circle(img, (x, y), 100, (255, 0, 0), -1)


# Create a black image, a window and bind the function to window
img = np.zeros((512, 512, 3), np.uint8)
cv.namedWindow('image')
cv.setMouseCallback('image', draw_circle)

while (1):
    cv.imshow('image', img)
    if cv.waitKey(20) & 0xFF == 27:
        break

cv.destroyAllWindows()

在这里插入图片描述

4. More Advanced Demo

Now we go for a much better application. In this, we draw either rectangles or circles (depending on the mode we select) by dragging the mouse like we do in Paint application. So our mouse callback function has two parts, one to draw rectangle and other to draw the circles. This specific example will be really helpful in creating and understanding some interactive applications like object tracking, image segmentation etc.
现在我们寻求更好的应用。在这里,我们通过拖动鼠标绘制矩形或圆形 (取决于我们选择的模式),就像我们在 Paint 应用程序中一样。所以我们的鼠标回调函数有两个部分,一个用于绘制矩形,另一个用于绘制圆形。这个具体的例子将非常有助于创建和理解一些交互式应用程序,如对象跟踪,图像分割等。

import numpy as np
import cv2 as cv
drawing = False # true if mouse is pressed
mode = True # if True, draw rectangle. Press 'm' to toggle to curve
ix,iy = -1,-1
# mouse callback function
def draw_circle(event,x,y,flags,param):
    global ix,iy,drawing,mode
    if event == cv.EVENT_LBUTTONDOWN:
        drawing = True
        ix,iy = x,y
    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)

Next we have to bind this mouse callback function to OpenCV window. In the main loop, we should set a keyboard binding for key ‘m’ to toggle between rectangle and circle.
接下来,我们必须将此鼠标回调函数绑定到 OpenCV 窗口。在主循环中,我们应该为键 ‘m’ 设置键盘绑定以在矩形和圆之间切换。

img = np.zeros((512,512,3), np.uint8)
cv.namedWindow('image')
cv.setMouseCallback('image',draw_circle)
while(1):
    cv.imshow('image',img)
    k = cv.waitKey(1) & 0xFF
    if k == ord('m'):
        mode = not mode
    elif k == 27:
        break
cv.destroyAllWindows()
#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
cv.setMouseCallback()
Our mouse callback function has two parts, one to draw rectangle and other to draw the circles.
"""

import numpy as np
import cv2 as cv

drawing = False  # true if mouse is pressed
mode = True  # if True, draw rectangle. Press 'm' to toggle to curve
ix, iy = -1, -1


# mouse callback function
def draw_circle(event, x, y, flags, param):
    global ix, iy, drawing, mode
    if event == cv.EVENT_LBUTTONDOWN:
        drawing = True
        ix, iy = x, y
    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)


img = np.zeros((512, 512, 3), np.uint8)
cv.namedWindow('image')
cv.setMouseCallback('image', draw_circle)

while (1):
    cv.imshow('image', img)

    k = cv.waitKey(1) & 0xFF
    if k == ord('m'):
        mode = not mode
    elif k == 27:
        break
cv.destroyAllWindows()

4.1 rectangle

在这里插入图片描述

4.2 circle

在这里插入图片描述

5. Additional Resources

#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
cv.setMouseCallback()
Our mouse callback function has two parts, one to draw rectangle and other to draw the circles.
"""

import numpy as np
import cv2 as cv

drawing = False  # true if mouse is pressed
mode = True  # if True, draw rectangle. Press 'm' to toggle to curve
ix, iy = -1, -1


# mouse callback function
def draw_circle(event, x, y, flags, param):
    global ix, iy, drawing, mode
    if event == cv.EVENT_LBUTTONDOWN:
        drawing = True
        ix, iy = x, y
    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)


img = np.zeros((512, 512, 3), np.uint8)
cv.namedWindow('image')
cv.setMouseCallback('image', draw_circle)

while (1):
    cv.imshow('image', img)

    k = cv.waitKey(1) & 0xFF
    if k == ord('m'):
        mode = not mode
    elif k == 27:
        break
cv.destroyAllWindows()

5.1 rectangle

在这里插入图片描述

5.2 circle

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/chengyq116/article/details/89787756