I'm writing a Programm to crop inmages and my problem is I want that rectangle to have a specific aspect ratio (90:90) and is it possible to make the rectangle instead of the mouse, change its size with mousewheel and confirm with mouse click?
import cv2
import numpy as np
cropping = False
x_start, y_start, x_end, y_end = 0, 0, 0, 0
image = cv2.imread('example.jpg')
oriImage = image.copy()
def mouse_crop(event, x, y, flags, param):
# grab references to the global variables
global x_start, y_start, x_end, y_end, cropping
# if the left mouse button was DOWN, start RECORDING
# (x, y) coordinates and indicate that cropping is being
if event == cv2.EVENT_LBUTTONDOWN:
x_start, y_start, x_end, y_end = x, y, x, y
cropping = True
# Mouse is Moving
elif event == cv2.EVENT_MOUSEMOVE:
if cropping == True:
x_end, y_end = x, y
# if the left mouse button was released
elif event == cv2.EVENT_LBUTTONUP:
# record the ending (x, y) coordinates
x_end, y_end = x, y
cropping = False # cropping is finished
refPoint = [(x_start, y_start), (x_end, y_end)]
if len(refPoint) == 2: #when two points were found
roi = oriImage[refPoint[0][1]:refPoint[1][1], refPoint[0][0]:refPoint[1][0]]
cv2.imshow("Cropped", roi)
cv2.namedWindow("image")
cv2.setMouseCallback("image", mouse_crop)
while True:
i = image.copy()
if not cropping:
cv2.imshow("image", image)
elif cropping:
cv2.rectangle(i, (x_start, y_start), (x_end, y_end), (255, 0, 0), 2)
cv2.imshow("image", i)
cv2.waitKey(1)
# close all open windows
cv2.destroyAllWindows()
This is the basic structure you could use to do this. Create an initial rectangle on first click, resize the rectangle by scrolling up or down, then finalize the cropping by clicking again. You would need to add some checks to limit the rectangle when it goes out of the image bounds and when it goes "smaller than zero".
# if the left mouse button was released
if event == cv2.EVENT_LBUTTONUP:
# create rectangle
if not cropping:
x_start, y_start = x-20, y-20
x_end, y_end = x+20, y+20
cropping = True # cropping is finished
# finish cropping
else:
refPoint = [(x_start, y_start), (x_end, y_end)]
if len(refPoint) == 2: #when two points were found
roi = oriImage[refPoint[0][1]:refPoint[1][1], refPoint[0][0]:refPoint[1][0]]
cv2.imshow("Cropped", roi)
elif event == cv2.EVENT_MOUSEWHEEL:
print(flags)
# scroll up
if flags > 0:
x_start, y_start = x_start-2, y_start-2
x_end, y_end = x_end+2, y_end+2
# scroll down
else:
x_start, y_start = x_start+2, y_start+2
x_end, y_end = x_end-2, y_end-2
Thank you :) but i have still one problem my code looks now like this:
import cv2
import numpy as np
cropping = False
x_start, y_start, x_end, y_end = 0, 0, 0, 0
image = cv2.imread('example.jpg')
oriImage = image.copy()
def mouse_crop(event, x, y, flags, param):
# grab references to the global variables
global x_start, y_start, x_end, y_end, cropping
# if the left mouse button was DOWN, start RECORDING
# (x, y) coordinates and indicate that cropping is being
if event == cv2.EVENT_MOUSEMOVE:
x_start, y_start, x_end, y_end = x, y, x+96, y+96
cropping = True
# Mouse is Moving
# elif event == cv2.EVENT_MOUSEMOVE:
# if cropping == True:
# x_end, y_end = x, y
# if the left mouse button was released
elif event == cv2.EVENT_LBUTTONUP:
# record the ending (x, y) coordinates
# x_end, y_end = x, y
cropping = False # cropping is finished
refPoint = [(x_start, y_start), (x_end, y_end)]
if len(refPoint) == 2: #when two points were found
roi = oriImage[refPoint[0][1]:refPoint[1][1], refPoint[0][0]:refPoint[1][0]]
cv2.imshow("Cropped", roi)
elif event == cv2.EVENT_MOUSEWHEEL:
print(flags)
# scroll up
if flags > 0:
x_start, y_start = x_start-15, y_start-15
x_end, y_end = x_end+15, y_end+15
# scroll down
else:
x_start, y_start = x_start+15, y_start+15
x_end, y_end = x_end-15, y_end-15
cv2.namedWindow("image")
cv2.setMouseCallback("image", mouse_crop)
while True:
i = image.copy()
if not cropping:
cv2.imshow("image", image)
elif cropping:
cv2.rectangle(i, (x_start, y_start), (x_end, y_end), (255, 0, 0), 2)
cv2.imshow("image", i)
cv2.waitKey(1)
# close all open windows
cv2.destroyAllWindows()
my problem is: the rectangle follows my mouse, I can make it bigger and smaller with the mousewheel but if I made it bigger and the mouse moves, it gets small again
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)
I'd like to extract the lower and upper of HSV values from area after click and crop it by mouse in video instead of an image.
Note: if you run this code, press key "c" to see the values.
The source of the code: here or here with a good explanation how to work, he creates a good code to find them in video here but I'd like to use the mouse to extract them as average similar to this code.
I did it by image, but I'd like to use it in video.
How to convert it from image to video?
The full code.
import cv2
import numpy as np
x_start, y_start, x_end, y_end = 0, 0, 0, 0
cropping = False
getROI = False
refPt = []
# load the image, clone it, and setup the mouse callback function
image = cv2.imread('exp2.png')
clone = image.copy()
def click_and_crop(event, x, y, flags, param):
# grab references to the global variables
global x_start, y_start, x_end, y_end, cropping, getROI
# if the left mouse button was clicked, record the starting
# (x, y) coordinates and indicate that cropping is being
# performed
if event == cv2.EVENT_LBUTTONDOWN:
x_start, y_start, x_end, y_end = x, y, x, y
cropping = True
elif event == cv2.EVENT_MOUSEMOVE:
if cropping == True:
x_end, y_end = x, y
# check to see if the left mouse button was released
elif event == cv2.EVENT_LBUTTONUP:
# record the ending (x, y) coordinates and indicate that
# the cropping operation is finished
x_end, y_end = x, y
cropping = False
getROI = True
cv2.namedWindow("image")
cv2.setMouseCallback("image", click_and_crop)
# keep looping until the 'q' key is pressed
while True:
i = image.copy()
if not cropping and not getROI:
cv2.imshow("image", image)
# print 'fff'
elif cropping and not getROI:
cv2.rectangle(i, (x_start, y_start), (x_end, y_end), (0, 255, 0), 2)
cv2.imshow("image", i)
# print 'bbb'
elif not cropping and getROI:
cv2.rectangle(image, (x_start, y_start), (x_end, y_end), (0, 255, 0), 2)
cv2.imshow("image", image)
# print 'mmm'
key = cv2.waitKey(1) & 0xFF
# if the 'r' key is pressed, reset the cropping region
if key == ord("r"):
image = clone.copy()
getROI = False
# if the 'c' key is pressed, break from the loop
elif key == ord("c"): # please press "c" key to get values.
break
# if there are two reference points, then crop the region of interest
# from teh image and display it
refPt = [(x_start, y_start), (x_end, y_end)]
# print len(refPt)
if len(refPt) == 2:
roi = clone[refPt[0][1]:refPt[1][1], refPt[0][0]:refPt[1][0]]
cv2.imshow("ROI", roi)
hsvRoi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
print('min H = {}, min S = {}, min V = {}; max H = {}, max S = {}, max V = {}'.format(hsvRoi[:, :, 0].min(),
hsvRoi[:, :, 1].min(),
hsvRoi[:, :, 2].min(),
hsvRoi[:, :, 0].max(),
hsvRoi[:, :, 1].max(),
hsvRoi[:, :, 2].max()))
lower = np.array([hsvRoi[:, :, 0].min(), hsvRoi[:, :, 1].min(), hsvRoi[:, :, 2].min()])
upper = np.array([hsvRoi[:, :, 0].max(), hsvRoi[:, :, 1].max(), hsvRoi[:, :, 2].max()])
image_to_thresh = clone
hsv = cv2.cvtColor(image_to_thresh, cv2.COLOR_BGR2HSV)
kernel = np.ones((3, 3), np.uint8)
# for red color we need to masks.
mask = cv2.inRange(hsv, lower, upper)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
cv2.imshow("Mask", mask)
cv2.waitKey(0)
# close all open windows
cv2.destroyAllWindows()
Please help me.
Thanks in advance.
after the
cv2.namedWindow("image")
cv2.setMouseCallback("image", click_and_crop)
replace your while True: with:
video_path = "your_video.mp4"
cap = cv2.VideoCapture(video_path)
while(cap.isOpened()):
ret, image = cap.read()
So the now the image is your frame from the video.
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 am trying to draw a circle a present coordinate when the mouse moves from one place to another in OpenCV screen
Right now I am able to see all the circle where the mouse has been moved from one place to another as mentioned below in the snap
But I need to display only one circle(present coordinate) while using EVENT_MOUSEMOVE in mouse events as mentioned in snapshot
mentioned below is my code
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
num += 1
x1, y1 = x, y
radius = int(math.sqrt((x - x1)**2 + (y - y1)**2))
print(radius)
cv2.circle(img, (x1,y1), radius, (255, 0, 0), 1)
if event == cv2.EVENT_MOUSEMOVE:
if drawing == True:
radius = 5
cv2.circle(img, (x, y), radius, (0, 0, 255), -1)
if event == cv2.EVENT_LBUTTONUP:
#drawing = False
num += 1
radius = int(math.sqrt((x - x1)**2 + (y - y1)**2))
print(radius)
cv2.circle(img, (x1,y1), radius, (255, 0, 255), 1)
if __name__ == "__main__":
num = 0
windowName = 'Drawing'
img = np.zeros((500, 500, 3), np.uint8)
cv2.namedWindow(windowName)
cv2.setMouseCallback(windowName, draw_circle)
while (True):
cv2.imshow(windowName, img)
if cv2.waitKey(20) == 27:
break
cv2.destroyAllWindows()
Suggestions will be very helpful