问题
I want to save an image from the video stream and then draw a rectangle onto the shown image to produce a region of interest. Later, save that ROI in a file. I used opencv python grabcut example to use the setMouseCallback function. But I don't know what I'm doing incorrect as it is not giving the result I expect. I would like to see the green rectangle drawn on the static image shown in mouse input
window and the roi being saved to file. Please help debug this code or show a better approach:
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()
回答1:
You need to reset the image everytime when the {event == cv2.EVENT_MOUSEMOVE:} called.
Your code should look something like this:
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:
This is my current work around where I again render the mouse input
window upon EVENT_LBUTTONUP
. To avoid the bounding box showing up in the ROI saved to file I use a copy of the inputed scene:
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()
Thus, I can visualize the rectangle which is supposed to bound the ROI but I still don't know how to visualize the bounding box while the mouse left button is down and the mouse cursor is moving. That visualization works in the grabcut example but I couldn't figure it out in my case. Upon uncommenting the line for drawing rectangle during EVENT_MOUSEMOVE
I get multiple rectangles drawn onto the image. If someone answers with a way to visualize a single rectangle as it is being created I can accept it.
来源:https://stackoverflow.com/questions/28823243/python-opencv-mouse-callback-for-drawing-rectangle