Drawing rectangle on image opencv?
Solution 1
You can think of the process as rendering in any other rendering API like OpenGL: to put something on the screen you clean it and then draw upon the clean area.
In this context cleaning means bringing back the original image. Drawing upon it means adding your rectangles or whatever.
So, what i recommend is creating a draw
method that only takes care of this. Call it whenever a change to the rendering target is meant to be made.
A quick snippet (not real python, just pseudocode):
source_image = Mat()
image = Mat()
rect = Rect()
# general logic and stuff ...
# set a mouseCallbackListener
def listener(evt):
rect.x = evt.x # uptade de rect properly (...)
draw()
# apply the drawing logic
def draw():
image = source_image.clone()
rectangle(image, rect, Scalar(0,255,0), 1, 8, 0)
imshow(WINDOW_NAME, image)
If you wish to see a real example, here's a C++11 code that let's you draw more than one triangle and then get their centers as output in response to keyboard input: https://gist.github.com/cirocosta/9f7a57bddb40c4e5cbca
Solution 2
I was able to achieve that in black background with the following code:-
import cv2
import numpy as np
drawing = False # true if mouse is pressed
mode = True # if True, draw rectangle. Press 'm' to toggle to curve
ix,iy = -1,-1
# mouse callback function
def draw_circle(event,x,y,flags,param):
global ix,iy,drawing,mode
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True
ix,iy = x,y
elif event == cv2.EVENT_MOUSEMOVE:
if drawing == True:
if mode == True:
cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),3)
q=x
w=y
if q!=x|w!=y:
cv2.rectangle(img,(ix,iy),(x,y),(0,0,0),-1)
else:
cv2.circle(img,(x,y),5,(0,0,255),-1)
elif event == cv2.EVENT_LBUTTONUP:
drawing = False
if mode == True:
cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),2)
else:
cv2.circle(img,(x,y),5,(0,0,255),-1)
img = np.zeros((512,512,3), np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)
while(1):
cv2.imshow('image',img)
k = cv2.waitKey(1) & 0xFF
if k == ord('m'):
mode = not mode
elif k == 27:
break
cv2.destroyAllWindows()
This was achieved by overlapping older rectangles with solid fill
Though if u want it over image , I can suggest watermarks
http://www.pyimagesearch.com/2016/03/07/transparent-overlays-with-opencv/
iec2011007
Updated on November 05, 2020Comments
-
iec2011007 over 3 years
I have loaded an image using opencv libraries in python and now i want to draw a rectangle using mouse but while drawing the rectangle the rectangle should be visible so that the person drawing it can place it in a way so that the object of interest is completely in rectangle but my code is producing not the desired output
my code is
import os import sys import numpy as np import cv2 baseDir = '/home/aman/Downloads/shirt/' filenames = next(os.walk(baseDir))[2] drawing = False # true if mouse is pressed mode = True # if True, draw rectangle. Press 'm' to toggle to curve ix,iy = -1,-1 tx,ty = -1,-1 def draw_circle(event,x,y,flags,param): global ix,iy,drawing,mode print 'aman' if event == cv2.EVENT_LBUTTONDOWN: drawing = True ix,iy = x,y elif event == cv2.EVENT_MOUSEMOVE: if drawing == True: if mode == True: #cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),-1) cv2.line(img, (ix,iy),(ix,y), 255, 1, 8, 0) cv2.line(img, (ix,iy),(x,iy), 255, 1, 8, 0) cv2.line(img, (ix,y),(x,y), 255, 1, 8, 0) cv2.line(img, (x,iy),(x,y), 255, 1, 8, 0) else: cv2.circle(img,(x,y),5,(0,0,255),-1) elif event == cv2.EVENT_LBUTTONUP: drawing = False if mode == True: #cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),-1) cv2.rectangle(img,(ix,y),(x,y),(0,255,0),-1) cv2.rectangle(img,(x,iy),(x,y),(0,255,0),-1) else: cv2.circle(img,(x,y),5,(0,0,255),-1) img = np.zeros((512,512,3), np.uint8) cv2.namedWindow('image') cv2.setMouseCallback('image',draw_circle) while(1): cv2.imshow('image',img) k = cv2.waitKey(1) & 0xFF if k == ord('m'): mode = not mode elif k == 27: break cv2.destroyAllWindows()
`
but the output produced is something like
I dont want this kind of behaviour i just want a single rectangle not for every movement. I know i should modify the code in mouse move event but the problem is how to do that so that when the person is moving the mouse he is able to see the complete rectangle and when he releases the button the rectangle should be fixed ?
-
Mailerdaimon over 9 yearsOpenCv draws the line directly into your image data. Either copy and restore for every new rectangle or use a proper Gui Toolkit.
-
beaker almost 9 yearsI really don't know how to do this in Python (hence the comment), but the idea is to draw each intermediate rectangle by doing XOR between the line color and the image color at each pixel. Then, before you draw the next rectangle, XOR again with the line color to undo the previous rectangle. In C++ you'd do this with LineIterator. Only on the final rectangle do you draw it normally in the final color.
-