[Reproduced] OpenCV+Python uses the mouse as a pen (8)

It is very useful to draw graphics with the mouse. In the following target tracking, we will use the mouse to mark the target to be tracked, and then track the target in real time, so today we will learn about some basic knowledge in OpenCV-mouse pen.

First need to understand a function:

cv2.setMouseCallback(windowName, MouseCallback , param=None)

Its various parameters are:

windowName: window name
MouseCallback: mouse response callback function
param: parameters passed by the response function

Here, we create a simple application, no matter where we double-click it, we can draw a circle on the image.

First, we create a mouse callback function, which is executed when a mouse event occurs. The function prototype is (this function is defined by ourselves, there is no such function in the OpenCV library, and the name can be defined arbitrarily):

MouseCallback (int event, int x, int y, int flags, void userdata)

The various parameters are:

event: a MouseEventTypes constant
x: the x coordinate of the
mouse y: the y coordinate of the mouse
flags: a MouseEventFlags constant
userdata: optional parameters

The mouse event can be anything related to the mouse, such as left button press, right button press, left button double click, etc. It provides us with the coordinates (x, y) of each mouse event. Through this event and location, we can do whatever we like. To list all available parameters, we run the following code in the pycharm terminal:

	view plaincopy to clipboardprint?
1.import cv2 as cv  
2.  
3.events = [i for i in dir(cv) if 'EVENT' in i]  
4.print( events )  

If we look at the output, we will find a lot of parameter names:

	view plaincopy to clipboardprint?
1.['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']  

Now we look at the event parameter in the MouseCallback function, which represents a MouseEventFlags constant:

MouseEventFlags :

cv.EVENT_FLAG_LBUTTON = 1, left-click and drag

cv.EVENT_FLAG_RBUTTON = 2, right-click and drag

cv.EVENT_FLAG_MBUTTON = 4, hold the middle button

cv.EVENT_FLAG_CTRLKEY = 8, press and hold ctrl

cv.EVENT_FLAG_SHIFTKEY = 16, hold down shift

cv.EVENT_FLAG_ALTKEY = 32, press and hold alt

Continue to look at the flags parameter in the MouseCallback function, which represents a MouseEventFlags constant:

cv.MouseEventTypes :

cv.EVENT_MOUSEMOVE = 0, mouse movement

cv.EVENT_LBUTTONDOWN = 1, press the left button

cv.EVENT_RBUTTONDOWN = 2, right click

cv.EVENT_MBUTTONDOWN = 3, press the middle button

cv.EVENT_LBUTTONUP = 4, left button release

cv.EVENT_RBUTTONUP = 5, right click to release

cv.EVENT_MBUTTONUP = 6, middle button release

cv.EVENT_LBUTTONDBLCLK = 7, double left click

cv.EVENT_RBUTTONDBLCLK = 8, right-click and double-click

cv.EVENT_MBUTTONDBLCLK = 9, Zhongjian double click

cv.EVENT_MOUSEWHEEL = 10, scroll wheel sliding

cv.EVENT_MOUSEHWHEEL = 11 horizontal scroll wheel sliding

Next we can start the experiment, creating a mouse callback function has a specific format, the format is the same in all places. It differs only in function. So, now we use the mouse callback function to do one thing, draw a circle where we double-click:

	view plaincopy to clipboardprint?
1.import numpy as np  
2.import cv2 as cv  
3.
4.  
5.def draw_circle(event, x, y, flags, param):  
6.  if event == cv.EVENT_LBUTTONDBLCLK:  
7.      cv.circle(img, (x, y), 100, (255, 0, 0), -1)  
8.
9.
10.img = np.zeros((512, 512, 3), np.uint8)  
11.cv.namedWindow('image')  
12.cv.setMouseCallback('image', draw_circle)  
13.while (1):  
14. cv.imshow('image', img)  
15. if cv.waitKey(20) & 0xFF == 27:  
16.     break  
17.cv.destroyAllWindows()  

Insert picture description here

The parameter we call here is EVENT_LBUTTONDBLCLK, which means that the mouse is double-clicked to trigger. If we double-click any area, a circle will be created with this as the center:

Mouse drawing graphics

Now we need to perform more advanced operations. In this case, we drag the mouse to draw a rectangle or circle (depending on the mode we choose) as in the "Drawing" application. Therefore, our mouse callback function has two parts, one for drawing a rectangle and the other for drawing a circle. This will be very helpful. In the later manual target tracking, we will manually mark these graphics with the mouse to complete real-time target tracking.

Now we come to implement a comprehensive example, this example will help you understand some ideas of image interaction:

Use the mouse to draw a picture on the image, you can draw a circle or a rectangle, press the q key to switch between the two modes. When the left button is pressed, it starts to draw, moves to where to draw, and ends when the left button is released. Sounds complicated, doesn't it? Step by step analysis:

· Draw with the mouse: Need to define the mouse callback function mouse_event

· Draw circle or rectangle: need to define a drawing mode mode

· Left click, move, release: need to capture three different events

· Start drawing, end drawing: need to define a drawing mark bit drawing

Okay, start code:

	

```python
	view plaincopy to clipboardprint?
1. import numpy as np  
2. import cv2 as cv  
3.
4. drawing = False  # true if mouse is pressed  
5. mode = True  # if True, draw rectangle. Press 'm' to toggle to curve  
6. ix, iy = -1, -1  
7.
8. mouse callback function
9.
10.def draw_circle(event, x, y, flags, param):  
11. global ix, iy, drawing, mode  
12. if event == cv.EVENT_LBUTTONDOWN:  
13.     drawing = True  
14.     ix, iy = x, y  
15. elif event == cv.EVENT_MOUSEMOVE:  
16.     if drawing:  
17.         if mode:  
18.             cv.rectangle(img, (ix, iy), (x, y), (0, 255, 0), -1)  
19.         else:  
20.             cv.circle(img, (x, y), 5, (0, 0, 255), -1)  
21. elif event == cv.EVENT_LBUTTONUP:  
22.     drawing = False  
23.     if mode:  
24.         cv.rectangle(img, (ix, iy), (x, y), (0, 255, 0), -1)  
25.     else:  
26.         cv.circle(img, (x, y), 5, (0, 0, 255), -1)  
27.  
28.  
29.img = np.zeros((512, 512, 3), np.uint8)  
30.cv.namedWindow('image')  
31.cv.setMouseCallback('image', draw_circle)  
32.while 1:  
33.    cv.imshow('image', img)  
34. k = cv.waitKey(1) & 0xFF  
35. if k == ord('q'):  
36.     mode = not mode  
37. elif k == 27:  
38.     break  
39.cv.destroyAllWindows()  

effect:
Insert picture description here

ok, done.

But what if we want to create an unfilled rectangle?

Then we need to modify the code. As mentioned in the previous section, functions such as drawing rectangle function and drawing circle function. When their last parameter is -1, it means solid, and when it is greater than 0, it is Hollow, if we define it as 1, then the thickness of the outline of the drawn figure is 1. Let’s look at the code:

	view plaincopy to clipboardprint?
1. import numpy as np  
2. import cv2 as cv  
3.  
4. drawing = False  # true if mouse is pressed  
5. mode = True  # if True, draw rectangle. Press 'm' to toggle to curve  
6. ix, iy = -1, -1  
7.
8.
9. # mouse callback function  
10.def draw_circle(event, x, y, flags, param):  
11.global ix, iy, drawing, mode  
12.if event == cv.EVENT_LBUTTONDOWN:  
13.     drawing = True  
14.     ix, iy = x, y  
15. elif event == cv.EVENT_MOUSEMOVE:  
16.     if drawing:  
17.         if mode:  
18.             tmp = img.copy()  
19.             cv.rectangle(tmp, (ix, iy), (x, y), (0, 255, 0), 1)  
20.             cv.imshow('image', tmp)  
21. elif event == cv.EVENT_LBUTTONUP:  
22.     drawing = False  
23.     if mode:  
24.          cv.rectangle(img, (ix, iy), (x, y), (0, 255, 0), 1)  
25.
26.
27.img = np.zeros((512, 512, 3), np.uint8)  
28.cv.namedWindow('image')  
29.cv.setMouseCallback('image', draw_circle)  
30.cv.imshow("image",img)  
31.while 1:  
32. k = cv.waitKey(1) & 0xFF  
33. if k == 27:  
34.     break  
35.cv.destroyAllWindows() 

Let's look at the effect:

image.png

Now we can also modify the code. We cancel the function executed by the parameter statement of EVENT_LBUTTONUP, so that when we draw the next rectangle, the previous one will be automatically cleared:

	view plaincopy to clipboardprint?
1. import numpy as np  
2. import cv2 as cv  
3.
4. drawing = False  # true if mouse is pressed  
5. mode = True  # if True, draw rectangle. Press 'm' to toggle to curve  
6. ix, iy = -1, -1  
7.
8.
9. # mouse callback function  
10.def draw_circle(event, x, y, flags, param):  
11. global ix, iy, drawing, mode  
12. if event == cv.EVENT_LBUTTONDOWN:  
13.     drawing = True  
14.     ix, iy = x, y  
15. elif event == cv.EVENT_MOUSEMOVE:  
16.     if drawing:  
17.         if mode:  
18.             tmp = img.copy()  
19.             cv.rectangle(tmp, (ix, iy), (x, y), (0, 255, 0), 1)  
20.             cv.imshow('image', tmp)  
21. elif event == cv.EVENT_LBUTTONUP:  
22.     drawing = False  
23.     # if mode:  
24.     #      cv.rectangle(img, (ix, iy), (x, y), (0, 255, 0), 1)  
25.
26.
27.img = np.zeros((512, 512, 3), np.uint8)  
28.cv.namedWindow('image')  
29.cv.setMouseCallback('image', draw_circle)  
30.cv.imshow("image",img)  
31.while 1:  
32. k = cv.waitKey(1) & 0xFF  
33. if k == 27:  
34.     break  
35.cv.destroyAllWindows()  

effect:

image.png

At this point, even if the mouse drawing part of OpenCV is over, if you want to master it, you should practice more by yourself.

Check the article summary page https://blog.csdn.net/weixin_44237705/article/details/107864965
More openvino technical information can be exchanged in the group~
Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_44237705/article/details/107972630