【问题标题】:Python OpenCV: mouse callback for drawing rectanglePython OpenCV:绘制矩形的鼠标回调
【发布时间】:2015-03-03 02:47:46
【问题描述】:

我想保存视频流中的图像,然后在显示的图像上绘制一个矩形以生成感兴趣区域。稍后,将该 ROI 保存在文件中。我使用 opencv python grabcut 示例来使用 setMouseCallback 函数。但我不知道我做错了什么,因为它没有给出我期望的结果。我想看到在mouse input 窗口中显示的静态图像上绘制的绿色矩形,并将 roi 保存到文件中。请帮助调试此代码或展示更好的方法:

import cv2

rect = (0,0,1,1)
rectangle = False
rect_over = False  
def onmouse(event,x,y,flags,params):
    global sceneImg,rectangle,rect,ix,iy,rect_over

    # Draw Rectangle
    if event == cv2.EVENT_LBUTTONDOWN:
        rectangle = True
        ix,iy = x,y

    elif event == cv2.EVENT_MOUSEMOVE:
        if rectangle == True:
            cv2.rectangle(sceneImg,(ix,iy),(x,y),(0,255,0),2)
            rect = (min(ix,x),min(iy,y),abs(ix-x),abs(iy-y))

    elif event == cv2.EVENT_LBUTTONUP:
        rectangle = False
        rect_over = True
        cv2.rectangle(sceneImg,(ix,iy),(x,y),(0,255,0),2)
        rect = (min(ix,x),min(iy,y),abs(ix-x),abs(iy-y))

        x1,y1,w,h = rect        
        roi = sceneImg[y1:y1+h, x1:x1+w]

        cv2.imwrite('roi.jpg', roi)

# Named window and mouse callback
cv2.namedWindow('video')
cv2.namedWindow('mouse input')
cv2.setMouseCallback('mouse input',onmouse)

camObj = cv2.VideoCapture(-1)
keyPressed = None
running = True
scene = False
# Start video stream
while running:
    readOK, frame = camObj.read()

    keyPressed = cv2.waitKey(5)
    if keyPressed == ord('s'):
        scene = True

        cv2.imwrite('sceneImg.jpg',frame)
        sceneImg = cv2.imread('sceneImg.jpg')

        cv2.destroyWindow('video')
        cv2.imshow('mouse input', sceneImg)

    elif keyPressed == ord('r'):
        scene = False
        cv2.destroyWindow('mouse input')

    elif keyPressed == ord('q'):
        running = False

    if not scene:
        cv2.imshow('video', frame)

cv2.destroyAllWindows()
camObj.release()

【问题讨论】:

  • 你说它没有给出你期望的结果。结果如何?
  • @ChristopherPeterson 结果是 roi 没有保存,我在mouse input 窗口中看不到图像上的矩形。

标签: python opencv mouseevent draw


【解决方案1】:

每次调用 {event == cv2.EVENT_MOUSEMOVE:} 时,您都需要重置图像。

您的代码应如下所示:

if event == cv2.EVENT_LBUTTONDOWN:
    rectangle = True
    ix,iy = x,y

elif event == cv2.EVENT_MOUSEMOVE:
    if rectangle == True:
        sceneImg = sceneImg2.copy()
        cv2.rectangle(sceneImg,(ix,iy),(x,y),(0,255,0),2)
        rect = (min(ix,x),min(iy,y),abs(ix-x),abs(iy-y))


elif event == cv2.EVENT_LBUTTONUP:
    rectangle = False
    rect_over = True

    cv2.rectangle(sceneImg,(ix,iy),(x,y),(0,255,0),2)
    rect = (min(ix,x),min(iy,y),abs(ix-x),abs(iy-y))

【讨论】:

    【解决方案2】:

    这是我目前的工作,我再次在EVENT_LBUTTONUP 上渲染mouse input 窗口。为了避免边界框出现在保存到文件的 ROI 中,我使用了输入场景的副本:

    import cv2
    
    rect = (0,0,1,1)
    rectangle = False
    rect_over = False  
    def onmouse(event,x,y,flags,params):
        global sceneImg,rectangle,rect,ix,iy,rect_over, roi
    
        # Draw Rectangle
        if event == cv2.EVENT_LBUTTONDOWN:
            rectangle = True
            ix,iy = x,y
    
        elif event == cv2.EVENT_MOUSEMOVE:
            if rectangle == True:
    #            cv2.rectangle(sceneCopy,(ix,iy),(x,y),(0,255,0),1)
                rect = (min(ix,x),min(iy,y),abs(ix-x),abs(iy-y))
    
        elif event == cv2.EVENT_LBUTTONUP:
            rectangle = False
            rect_over = True
    
            sceneCopy = sceneImg.copy()
            cv2.rectangle(sceneCopy,(ix,iy),(x,y),(0,255,0),1)
    
            rect = (min(ix,x),min(iy,y),abs(ix-x),abs(iy-y))       
            roi = sceneImg[rect[1]:rect[1]+rect[3], rect[0]:rect[0]+rect[2]]
    
            cv2.imshow('mouse input', sceneCopy)
            cv2.imwrite('roi.jpg', roi)
    
    # Named window and mouse callback
    cv2.namedWindow('mouse input')
    cv2.setMouseCallback('mouse input',onmouse)
    cv2.namedWindow('video')
    
    camObj = cv2.VideoCapture(-1)
    keyPressed = None
    running = True
    scene = False
    # Start video stream
    while running:
        readOK, frame = camObj.read()
    
        keyPressed = cv2.waitKey(5)
        if keyPressed == ord('s'):
            scene = True
            cv2.destroyWindow('video')
    
            cv2.imwrite('sceneImg.jpg',frame)
            sceneImg = cv2.imread('sceneImg.jpg')
    
            cv2.imshow('mouse input', sceneImg)
    
        elif keyPressed == ord('r'):
            scene = False
            cv2.destroyWindow('mouse input')
    
        elif keyPressed == ord('q'):
            running = False
    
        if not scene:
            cv2.imshow('video', frame)
    
    cv2.destroyAllWindows()
    camObj.release()
    

    因此,我可以可视化应该限制 ROI 的矩形,但我仍然不知道如何在鼠标左键按下且鼠标光标移动时可视化边界框。该可视化在抓取示例中有效,但在我的情况下我无法弄清楚。在EVENT_MOUSEMOVE 期间取消注释绘制矩形的线后,我在图像上绘制了多个矩形。如果有人以一种在创建单个矩形时可视化的方式回答,我可以接受。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-29
      • 1970-01-01
      • 2015-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多