简体   繁体   English

opencv上的鼠标事件

[英]mouse events on opencv

I am trying to write a function which will open an image and draw a circle where the left mouse button is clicked.我正在尝试编写一个函数,该函数将打开一个图像并在单击鼠标左键的位置绘制一个圆圈。 the circle's size can then be adjusted using the mousewheel/keyboard.然后可以使用鼠标滚轮/键盘调整圆圈的大小。 Also, every click will print a label in sequence eg 1st circle puts label '1', 2nd circle drawn puts a label'2' and so on.此外,每次点击都会按顺序打印一个标签,例如第一个圆圈放置标签“1”,绘制的第二个圆圈放置标签“2”等等。 I have managed to get the circle and the label on the image but i am unsure how to increase the radius or change the label with different clicks .我已经设法在图像上获得圆圈和标签,但我不确定如何增加半径通过不同的点击更改标签

import cv2
import numpy as np

# Create a black image and a window
windowName = 'Drawing'
img = cv2.imread('000025.png',cv2.IMREAD_COLOR)
cv2.namedWindow(windowName)








# mouse callback function
def draw_circle(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        cv2.circle(img, (x,y), 30, (255, 0,), 1)
        font = cv2.FONT_HERSHEY_SIMPLEX
        cv2.putText(img,'label' , (x + 30, y + 30), font, 1, (200, 255, 155), 1, cv2.LINE_AA)




# bind the callback function to window
cv2.setMouseCallback(windowName, draw_circle)


def main():
    while (True):
        cv2.imshow(windowName, img)
        if cv2.waitKey(20) == 27:
            break

    cv2.destroyAllWindows()


if __name__ == "__main__":
    main()

Using the following code you can visualize the circle while moving the mouse as well.使用以下代码,您还可以在移动鼠标的同时可视化圆圈。 I have supplemented the code provided by Salman by adding another condition involving MOUSEMOVE event.我通过添加另一个涉及MOUSEMOVE事件的条件来补充 Salman 提供的代码。

import cv2
import numpy as np
import math

drawing = False

def draw_circle(event, x, y, flags, param):
    global x1, y1, drawing, radius, num, img, img2
    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        x1, y1 = x, y
        radius = int(math.hypot(x - x1, y - y1))
        cv2.circle(img, (x1,y1), radius, (255, 0, 0), 1)

    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing == True:
            a, b = x, y
            if a != x & b != y:
                img = img2.copy()
                radius = int(math.hypot(a - x1, b - y1))
                cv2.circle(img, (x1,y1), radius, (255, 0, 0), 1)

    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        num += 1
        radius = int(math.hypot(x - x1, y - y1))
        cv2.circle(img, (x1,y1), radius, (255, 0, 255), 1)
        font = cv2.FONT_HERSHEY_SIMPLEX
        cv2.putText(img, '_'.join(['label', str(num)]), (x + 20, y + 20), font, 1, (200, 255, 155), 1, cv2.LINE_AA)
        img2 = img.copy()


if __name__ == "__main__":
    num = 0
    windowName = 'Drawing'

    img = np.zeros((500, 500, 3), np.uint8)
    img2 = img.copy()
    cv2.namedWindow(windowName)
    cv2.setMouseCallback(windowName, draw_circle)
    while (True):
        cv2.imshow(windowName, img)
        if cv2.waitKey(20) == 27:
            break

    cv2.destroyAllWindows()

Sample output:示例输出:

在此处输入图片说明

I think this may works for you:我认为这可能对你有用:

import cv2
import numpy as np
import math


# mouse callback function
def draw_circle(event, x, y, flags, param):
    global x1, y1, radius, num
    if event == cv2.EVENT_LBUTTONDOWN:
        x1, y1 = x, y

    if event == cv2.EVENT_LBUTTONUP:
        num += 1
        radius = int(math.hypot(x - x1, y - y1))
        cv2.circle(img, (x1,y1), radius, (255, 0,), 1)

        font = cv2.FONT_HERSHEY_SIMPLEX
        cv2.putText(img, f'label: {num}', (x + 30, y + 30), font, 1, (200, 255, 155), 1, cv2.LINE_AA)


if __name__ == "__main__":
    num = 0
    # Create a black image and a window
    windowName = 'Drawing'
    img = cv2.imread('img.jpg', cv2.IMREAD_COLOR)
    cv2.namedWindow(windowName)
    # bind the callback function to window
    cv2.setMouseCallback(windowName, draw_circle)
    while (True):
        cv2.imshow(windowName, img)
        if cv2.waitKey(20) == 27:
            break

    cv2.destroyAllWindows()

Result:结果: 在此处输入图片说明

This is a simple code and you can do a lot of things with mouse events.这是一个简单的代码,你可以用鼠标事件做很多事情。

First you have to keep all coordinates (or other attributes) of your drawables in global dynamic object.首先,您必须将可绘制对象的所有坐标(或其他属性)保留在全局动态对象中。

You have to give guidance to the app, if you are drawing circle, label or other drawable.如果您正在绘制圆圈、标签或其他可绘制对象,则必须为应用程序提供指导。 It can be done by creating menu items in the OpenCV window or by key presses (I have done both).它可以通过在 OpenCV 窗口中创建菜单项或通过按键来完成(我都做过)。 You have to keep track of context (is next click x,y coords of center of cirle, point in the circle (for radius calc, unless you decide to use mousewheel/kbd for it) left-up corner of rectangle, etc.您必须跟踪上下文(下一次单击圆心的 x、y 坐标、圆中的点(对于半径计算,除非您决定使用鼠标滚轮/kbd)、矩形的左上角等。

You have to store the created drawables in the said global object.您必须将创建的可绘制对象存储在所述全局对象中。

If you want to edit/delete the existing drawable, you have to make iterator function, that detects closest drawable (by its mid- or other point) for proper selection.如果要编辑/删除现有的可绘制对象,则必须创建迭代器函数,该函数会检测最近的可绘制对象(通过其中间点或其他点)以进行正确选择。

All above is doable in OpenCV alone.以上所有内容单独在 OpenCV 中都是可行的。

Python class implementation of getting mouse click points in an image using OpenCV mouse click callback.使用 OpenCV 鼠标单击回调在图像中获取鼠标单击点的 Python 类实现。 You can make an object of this class and use getpt(n, img) method to select n points in an image using mouse click.您可以创建此类的对象并使用 getpt(n, img) 方法使用鼠标单击在图像中选择 n 个点。 Edit and use for your purpose.根据您的目的编辑和使用。

import cv2
import numpy as np
#events = [i for i in dir(cv2) if 'EVENT' in i]
#print (events)

class MousePts:
    def __init__(self,windowname,img):
        self.windowname = windowname
        self.img1 = img.copy()
        self.img = self.img1.copy()
        cv2.namedWindow(windowname,cv2.WINDOW_NORMAL)
        cv2.imshow(windowname,img)
        self.curr_pt = []
        self.point   = []

    def select_point(self,event,x,y,flags,param):
        if event == cv2.EVENT_LBUTTONDOWN:
            self.point.append([x,y])
            #print(self.point)
            cv2.circle(self.img,(x,y),5,(0,255,0),-1)
        elif event == cv2.EVENT_MOUSEMOVE:
            self.curr_pt = [x,y]
            #print(self.point)
                   
    def getpt(self,count=1,img=None):
        if img is not None:
            self.img = img
        else:
            self.img = self.img1.copy()
        cv2.namedWindow(self.windowname,cv2.WINDOW_NORMAL)
        cv2.imshow(self.windowname,self.img)
        cv2.setMouseCallback(self.windowname,self.select_point)
        self.point = []
        while(1):
            cv2.imshow(self.windowname,self.img)
            k = cv2.waitKey(20) & 0xFF
            if k == 27 or len(self.point)>=count:
                break
            #print(self.point)
        cv2.setMouseCallback(self.windowname, lambda *args : None)
        #cv2.destroyAllWindows()
        return self.point, self.img
         
if __name__=='__main__':
    img = np.zeros((512,512,3), np.uint8)
    windowname = 'image'
    coordinateStore = MousePts(windowname,img)

    pts,img = coordinateStore.getpt(3)
    print(pts)
        
    pts,img = coordinateStore.getpt(3,img)
    print(pts)
    
    cv2.imshow(windowname,img)
    cv2.waitKey(0)
    

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM