I am trying to draw two zones by clicking by mouse events and i thought about using two threads and a lock and here is my code :
import numpy as np
import cv2
from threading import Thread, RLock
CANVAS_SIZE = (600,800)
FINAL_LINE_COLOR = (255, 255, 255)
WORKING_LINE_COLOR = (127, 127, 127)
verrou = RLock()
class ZoneDrawer(Thread):
def __init__(self, window_name):
Thread.__init__(self)
self.window_name = window_name
self.done = False
self.current = (0, 0)
self.points = []
def on_mouse(self, event, x, y, buttons, user_param):
if event == cv2.EVENT_MOUSEMOVE:
self.current = (x, y)
elif event == cv2.EVENT_LBUTTONDOWN:
print("Adding point #%d with position(%d,%d)" % (len(self.points), x, y))
self.points.append((x, y))
elif event == cv2.EVENT_RBUTTONDOWN:
self.done = True
def run(self):
cv2.namedWindow(self.window_name)
cv2.imshow(self.window_name, np.zeros(CANVAS_SIZE, np.uint8))
cv2.waitKey(1)
cv2.setMouseCallback(self.window_name, self.on_mouse)
while(not self.done):
canvas = np.zeros(CANVAS_SIZE, np.uint8)
with verrou:
if (len(self.points) > 0):
cv2.polylines(canvas, np.array([self.points]), True, FINAL_LINE_COLOR, 1)
cv2.line(canvas, self.points[-1], self.current, WORKING_LINE_COLOR)
cv2.imshow(self.window_name, canvas)
if cv2.waitKey(50) == 27:
self.done = True
cv2.waitKey()
cv2.destroyWindow(self.window_name)
thread_1 = ZoneDrawer("zone1")
thread_2 = ZoneDrawer("zone2")
thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()
But this code is still not working. Any help or suggestion ?
The following scrip can be used to select regions of an image using the mouse (as seen in the .gif).
import cv2, numpy as np
# Mouse callback function
global click_list
positions, click_list, shapes = [(0,0)], [], []
def callback(event, x, y, flags, param):
positions[-1] = (x,y)
if event == 1: click_list.append((x,y))
cv2.namedWindow('img')
cv2.setMouseCallback('img', callback)
# Mainloop - show the image and collect the data
while True:
# Create a blank image
img = np.zeros((600,600,3), np.uint8)
# Try to draw the shape being collected
for idx in range(len(click_list)-1):
cv2.line(img, click_list[idx], click_list[idx+1], (0,255,0), 5)
# Draw the stored shapes
for shape in shapes:
for idx in range(len(shape)):
cv2.line(img, shape[idx], shape[idx-1], 255, 5)
# Show the image
cv2.imshow('img', img)
# Wait, and allow the user to quit with the 'esc' key
k = cv2.waitKey(1)
# If user presses 's', go on to the next shape
if k == 115:
shapes.append(click_list)
click_list = []
# If user presses 'esc' break
if k == 27: break
# Clean up
cv2.destroyAllWindows()
Related
import cv2
class ExtractImageWidget(object):
def __init__(self):
self.original_image = cv2.imread('0001.jpg')
# Resize image, remove if you want raw image size
self.original_image = cv2.resize(self.original_image, (640, 556))
self.clone = self.original_image.copy()
cv2.namedWindow('image')
cv2.setMouseCallback('image', self.extract_coordinates)
# Bounding box reference points and boolean if we are extracting coordinates
self.image_coordinates = []
self.extract = False
def extract_coordinates(self, event, x, y, flags, parameters):
# Record starting (x,y) coordinates on left mouse button click
if event == cv2.EVENT_LBUTTONDOWN:
self.image_coordinates = [(x,y)]
self.extract = True
# Record ending (x,y) coordintes on left mouse bottom release
elif event == cv2.EVENT_LBUTTONUP:
self.image_coordinates.append((x,y))
self.extract = False
print('top left: {}, bottom right: {}'.format(self.image_coordinates[0], self.image_coordinates[1]))
# Draw rectangle around ROI
cv2.rectangle(self.clone, self.image_coordinates[0], self.image_coordinates[1], (0,255,0), 2)
cv2.imshow("image", self.clone)
# Clear drawing boxes on right mouse button click
elif event == cv2.EVENT_RBUTTONDOWN:
self.clone = self.original_image.copy()
def show_image(self):
return self.clone
if __name__ == '__main__':
extract_image_widget = ExtractImageWidget()
while True:
cv2.imshow('image', extract_image_widget.show_image())
key = cv2.waitKey(1)
# Close program with keyboard 'q'
if key == ord('q'):
cv2.destroyAllWindows()
exit(1)
so i'm using opencv and i want to make a sort of selection tool but the problem is can't make the rectangle transparent. here's the code:
import numpy as np
import cv2 as cv
drawing = False
def draw_rec(event,x,y,flags,param):
global ix,iy,drawing
if event == cv.EVENT_LBUTTONDOWN:
drawing = True
ix,iy = x,y
elif event == cv.EVENT_LBUTTONUP:
drawing = False
cv.rectangle(img,(ix,iy),(x,y),(0,0,0),-1)
elif event == cv.EVENT_MOUSEMOVE:
if drawing == True:
cv.rectangle(img, (ix, iy), (x, y), (0, 255, 0), 5)
img = cv.imread('baboon.jpg', -1)
cv.namedWindow('image')
cv.setMouseCallback('image',draw_rec)
while(1):
cv.imshow('image',img)
k = cv.waitKey(1) & 0xFF
if k == 27:
break
cv.destroyAllWindows()
The first mistake in the code is:
elif event == cv.EVENT_LBUTTONUP:
drawing = False
cv.rectangle(img,(ix,iy),(x,y),(0,0,0),-1)
The -1 parameter means to fill the rectangle. source If we change -1 to 1:
From my point of view, the result is not satisfactory. The multiple rectangle display is caused by the mouse_movement.
elif event == cv.EVENT_MOUSEMOVE:
if drawing == True:
cv.rectangle(img, (ix, iy), (x, y), (0, 255, 0), 5)
Each time the mouse moves, the rectangle will be drawn. I think it is better if we draw when the mouse movement finishes:
Code:
import numpy as np
import cv2 as cv
drawing = False
def draw_rec(event,x,y,flags,param):
global ix,iy,drawing
if event == cv.EVENT_LBUTTONDOWN:
drawing = True
ix,iy = x,y
elif event == cv.EVENT_LBUTTONUP:
drawing = False
cv.rectangle(img,(ix,iy),(x,y),(0,255,0),5)
img = cv.imread('27BR1.jpg', -1)
cv.namedWindow('image')
cv.setMouseCallback('image',draw_rec)
while(1):
cv.imshow('image',img)
k = cv.waitKey(1) & 0xFF
if k == 27:
break
cv.destroyAllWindows()
I am currently trying to implement a function that will allow me to use the cursor to "grab" a video and move it around. I want to be able to only move the video when the cursor is held down and moved. I have defined the mouse events, captured the coordinates of my cursor but I am not sure how to write the function to crop the video.
x1, x2, y1, y2 = 0, 0, 0, 0
mouse_down = False
def mouse_event_callback(event, x, y, flags, param):
global x1, x2, y1, y2, mouse_down
if event == cv2.EVENT_LBUTTONDOWN:
x1, y1 = x, y
mouse_down = True
elif event == cv2.EVENT_MOUSEMOVE:
if mouse_down:
x2, y2 = x, y
mouse_grab_video(x1, x2, y1, y2)
elif event == cv2.EVENT_LBUTTONUP:
mouse_down = False
def mouse_grab_video(x1, x2, y1, y2):
...
Any help would be much appreciated!
You can crop the image directly based on the coordinate you get from your mouse event.
#!/usr/bin/env python3
import argparse
import cv2
import numpy as np
from PIL import Image
drawing = False # true if mouse is pressed
ix,iy = -1,-1
refPt = []
img = ""
clone = ""
ROIRegion = []
# mouse callback function
def draw_rectangle(event,x,y,flags,param):
global ix,iy,drawing,img,clone,refPt, ROIRegion
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True
ix,iy = x,y
refPt = [(x, y)]
ROIRegion.append(refPt)
#clone = img.copy()
elif event == cv2.EVENT_MOUSEMOVE:
if drawing == True:
img = clone.copy()
cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),3)
a=x
b=y
if a != x | b != y:
cv2.rectangle(img,(ix,iy),(x,y),(0,0,0),-1)
elif event == cv2.EVENT_LBUTTONUP:
drawing = False
refPt.append((x,y))
img = clone.copy()
cv2.rectangle(img, (ix,iy),(x,y), (0, 255, 0), 2)
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
args = vars(ap.parse_args())
img = cv2.imread(args["image"])
img = np.array(img)
clone = img.copy()
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_rectangle)
while(1):
cv2.imshow('image',img)
k = cv2.waitKey(1) & 0xFF
if k == ord("r"):
del ROIRegion[-1]
del refPt[-1]
img = clone.copy()
elif k == 27:
break
#Crop image to ROI
for region in range(len(ROIRegion)):
cv2.rectangle(img, ROIRegion[region][0],ROIRegion[region][1], (0, 255, 0), 2)
roi = clone[ROIRegion[region][0][1]:ROIRegion[region][1][1], ROIRegion[region][0][0]:ROIRegion[region][1][0]]
For zoom you may use EVENT_MOUSEWHEEL to increment scale and resize the image based on the scale. update imshow for latest image you scale. you can refer to this link
I'm newbie in python and i want to learn python. The code(below) is as same as the code i have written in C++. The code works fine in C++ but in python it's not.
My concern is when i hold mouse left button it should draw a circle on image but it's not.
Any help would be appreciated.
code:
import cv2 as cv
import numpy as np
class mouse_state:
def __init__(self):
self.position = [-1,-1]
self.left_button_held = False
self.left_button_clicked = False
def new_iteration():
left_button_clicked = False
def mouse_callback(event, x,y, flag, param):
param = mouse_state()
if event == cv.EVENT_LBUTTONDOWN:
param.position = (x,y)
param.left_button_held = True
print('LMB Down # ', param.position)
elif event == cv.EVENT_LBUTTONUP:
param.position = (x,y)
param.left_button_held = False
param.left_button_clicked = True
print('LMB Up # ', param.position)
elif (flag == cv.EVENT_FLAG_LBUTTON) and (event == cv.EVENT_MOUSEMOVE):
param.position = (x,y)
print('LMB Held, Mouse Moved To',param.position)
cap = cv.VideoCapture(0)
assert cap.isOpened()
windowName = 'Feed'
cv.namedWindow(windowName)
ms = mouse_state()
cv.setMouseCallback(windowName, mouse_callback, ms)
while True:
ret, frame = cap.read()
if not ret: break
(height, width) = frame.shape[:2]
if ms.left_button_clicked or ms.left_button_held:
cv.circle(frame, ms.position, 3, (0,0,255))
cv.circle(frame, ms.position, 10, (255,0,0), 2)
print('Current Position ', ms.position)
ms.new_iteration
cv.imshow(windowName, frame)
w = cv.waitKey(1)
if w == ord('q'):
break
cv.destroyAllWindows()
i am new to opencv -python.
I want to draw a rectangle in a live stream video captured from my webcam. While drawing the rectangle,the video must freeze. I am successful in drawing a rectangle on a image,but i don't know how to do the same on a live video using opencv and python . Please help..
This is a code that I'm using to draw a rectange in videos.
The code works like that:
click on video and the script save the start point
click again and the script save the end point and draw the rectangle
click again to start drawing another retangle
import numpy as np
import cv2
rect = (0,0,0,0)
startPoint = False
endPoint = False
def on_mouse(event,x,y,flags,params):
global rect,startPoint,endPoint
# get mouse click
if event == cv2.EVENT_LBUTTONDOWN:
if startPoint == True and endPoint == True:
startPoint = False
endPoint = False
rect = (0, 0, 0, 0)
if startPoint == False:
rect = (x, y, 0, 0)
startPoint = True
elif endPoint == False:
rect = (rect[0], rect[1], x, y)
endPoint = True
cap = cv2.VideoCapture('../videos/sample.avi')
waitTime = 50
#Reading the first frame
(grabbed, frame) = cap.read()
while(cap.isOpened()):
(grabbed, frame) = cap.read()
cv2.namedWindow('frame')
cv2.setMouseCallback('frame', on_mouse)
#drawing rectangle
if startPoint == True and endPoint == True:
cv2.rectangle(frame, (rect[0], rect[1]), (rect[2], rect[3]), (255, 0, 255), 2)
cv2.imshow('frame',frame)
key = cv2.waitKey(waitTime)
if key == 27:
break
cap.release()
cv2.destroyAllWindows()