opencv上的鼠标事件
mouse events on opencv
我正在尝试编写一个函数,该函数将打开一个图像并在单击鼠标左键的位置绘制一个圆圈。然后可以使用 mousewheel/keyboard 调整圆的大小。此外,每次点击都会按顺序打印标签,例如第一个圆圈放置标签“1”,绘制的第二个圆圈放置标签“2”,依此类推。我已经设法在图像上获得圆圈和标签,但我不确定如何增加半径 或通过不同的点击更改标签。
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()
首先,您必须将可绘制对象的所有坐标(或其他属性)保存在全局动态对象中。
如果您正在绘制圆圈、标签或其他可绘制对象,则必须对应用程序进行指导。这可以通过在 OpenCV window 中创建菜单项或通过按键来完成(我都做过)。您必须跟踪上下文(下一步是单击 x,圆心的 y 坐标,圆中的点(对于半径计算,除非您决定对其使用 mousewheel/kbd)矩形的左上角等.
您必须将创建的可绘制对象存储在所述全局对象中。
如果你想 edit/delete 现有的可绘制对象,你必须制作迭代器函数,它检测最近的可绘制对象(通过其中间点或其他点)以进行正确选择。
以上仅在 OpenCV 中就可以实现。
我认为这可能适合你:
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()
结果:
这是一个简单的代码,您可以使用鼠标事件做很多事情。
使用以下代码,您也可以在移动鼠标的同时可视化圆圈。我通过添加另一个涉及 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()
示例输出:
Python class 使用 OpenCV 鼠标点击回调在图像中获取鼠标点击点的实现。您可以创建此 class 的对象并使用 getpt(n, img) 方法使用鼠标单击图像中的 select n 个点。为您的目的编辑和使用。
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)
我正在尝试编写一个函数,该函数将打开一个图像并在单击鼠标左键的位置绘制一个圆圈。然后可以使用 mousewheel/keyboard 调整圆的大小。此外,每次点击都会按顺序打印标签,例如第一个圆圈放置标签“1”,绘制的第二个圆圈放置标签“2”,依此类推。我已经设法在图像上获得圆圈和标签,但我不确定如何增加半径 或通过不同的点击更改标签。
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()
首先,您必须将可绘制对象的所有坐标(或其他属性)保存在全局动态对象中。
如果您正在绘制圆圈、标签或其他可绘制对象,则必须对应用程序进行指导。这可以通过在 OpenCV window 中创建菜单项或通过按键来完成(我都做过)。您必须跟踪上下文(下一步是单击 x,圆心的 y 坐标,圆中的点(对于半径计算,除非您决定对其使用 mousewheel/kbd)矩形的左上角等.
您必须将创建的可绘制对象存储在所述全局对象中。
如果你想 edit/delete 现有的可绘制对象,你必须制作迭代器函数,它检测最近的可绘制对象(通过其中间点或其他点)以进行正确选择。
以上仅在 OpenCV 中就可以实现。
我认为这可能适合你:
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()
结果:
这是一个简单的代码,您可以使用鼠标事件做很多事情。
使用以下代码,您也可以在移动鼠标的同时可视化圆圈。我通过添加另一个涉及 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()
示例输出:
Python class 使用 OpenCV 鼠标点击回调在图像中获取鼠标点击点的实现。您可以创建此 class 的对象并使用 getpt(n, img) 方法使用鼠标单击图像中的 select n 个点。为您的目的编辑和使用。
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)