How to have normal speed of output video in my Dense Optical Flow model? - opencv

My code below is from https://docs.opencv.org/3.4/d4/dee/tutorial_optical_flow.html, idk why the output video is so slow, how to change back to normal speed guys?
cap = cv.VideoCapture('NY.avi')
ret, frame1 = cap.read()
prvs = cv.cvtColor(frame1,cv.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
hsv[...,1] = 255
while(1):
ret, frame2 = cap.read()
next = cv.cvtColor(frame2,cv.COLOR_BGR2GRAY)
flow = cv.calcOpticalFlowFarneback(prvs,next, None, 0.5, 3, 15, 3, 5, 1.2, 0)
mag, ang = cv.cartToPolar(flow[...,0], flow[...,1])
hsv[...,0] = ang*180/np.pi/2
hsv[...,2] = cv.normalize(mag,None,0,255,cv.NORM_MINMAX)
bgr = cv.cvtColor(hsv,cv.COLOR_HSV2BGR)
cv.imshow('frame2',bgr)
k = cv.waitKey(30) & 0xff
if k == 27:
break
elif k == ord('s'):
cv.imwrite('opticalfb.png',frame2)
cv.imwrite('opticalhsv.png',bgr)
prvs = next

Related

Why the output of Dense Optical Flow in OpenCV is not continuous?

I want to track whether worker throw garbage into the truck manually in the video.
Q1: Is Dense Optical Flow in OpenCV a good solution for me?
Q2: I tried to code a sample. But why the flow image is not continuous?
frame 41 and 43 is good , but frame 42 is black
Q3: Can I spy on the color change in a small area to track if garbage through ?
small area like this:
here is my code. you can run my code and video in my github repository
https://github.com/Pinocchio2018/QuestionHelper/blob/main/openCV_related/dence_optical_flow_problem/test.py
import numpy as np
import cv2 as cv
def put_frame_no(image, frame_no):
# font
font = cv.FONT_HERSHEY_SIMPLEX
# org
org = (50, 450)
# fontScale
font_scale = 2
# Blue color in BGR
color = (0, 0, 255)
# Line thickness of 2 px
thickness = 2
# Using cv2.putText() method
image = cv.putText(image, "frame no: " + str(frame_no), org, font,
font_scale, color, thickness, cv.LINE_AA)
return image
cap = cv.VideoCapture(cv.samples.findFile("0116-sample4-edited-short-throw.mp4"))
ret, frame1 = cap.read()
prv_frame = cv.cvtColor(frame1, cv.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
hsv[..., 1] = 255
cv.namedWindow("flow image", cv.WINDOW_NORMAL)
cv.resizeWindow("flow image", 800, 600)
frame_no = 0
while 1:
ret, origin_img = cap.read()
if not ret:
print('No frames grabbed!')
break
next_frame = cv.cvtColor(origin_img, cv.COLOR_BGR2GRAY)
flow = cv.calcOpticalFlowFarneback(prv_frame, next_frame, None, 0.5, 3, 15, 3, 5, 1.2, 0)
mag, ang = cv.cartToPolar(flow[..., 0], flow[..., 1])
hsv[..., 0] = ang * 180 / np.pi / 2
hsv[..., 2] = cv.normalize(mag, None, 0, 255, cv.NORM_MINMAX)
flow_image = cv.cvtColor(hsv, cv.COLOR_HSV2BGR)
flow_image = put_frame_no(flow_image, frame_no)
origin_img = put_frame_no(origin_img, frame_no)
frame_no += 1
vis_frame = np.concatenate((origin_img, flow_image), axis=1)
cv.imshow('flow image', vis_frame)
# cv.imshow('origin', flow_image)
k = cv.waitKey(30) & 0xff
if k == 27:
break
elif k == ord('s'):
cv.imwrite('opticalfb.png', origin_img)
cv.imwrite('opticalhsv.png', flow_image)
prv_frame = next_frame
cv.destroyAllWindows()

OpenCv Get edge distance to circle center

A bit off an intro, i need to make a visual aid to align sheets against fixed points.
My setup has 3 points, a sheetmetal plate needs to be positioned against these points using a forklift.
Its a gentle task, we cant use brut force to align the sheet, so i want to install camera's to help them align there sheetmetal plate.
Code so far:
import sys
import cv2 as cv
import numpy as np
cap = cv.VideoCapture(0)
val = 50
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
gray = cv.GaussianBlur(gray, (5,5), 0)
rows = gray.shape[0]
circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, 1, rows / 8,
param1=100, param2=30,
minRadius=1, maxRadius=30)
edges = cv.Canny(gray,val,val*3,apertureSize = 3)
lines = cv.HoughLines(edges,1.2,np.pi/180,200)
font = cv.FONT_HERSHEY_SIMPLEX
color = (255, 255, 255)
thickness = 2
index = 1
if len(circles[0]) > 2 :
circles = np.uint16(np.floor(circles))
circles2=sorted(circles[0],key=lambda x:x[0],reverse=False)
print (circles2)
for i in circles2:
center = (i[0], i[1])
cv.circle(frame, center, 1, (0, 255, 0), 3)
text = str(index) +' ' + str(i[0]) +' ' + str(i[1])
cv.putText(frame, text, center, font, 1, color, thickness, cv.LINE_AA)
index += 1
cv.imshow("detected circles", frame)
cv.imshow("detected edges", edges)
if cv.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv.destroyAllWindows()
So the points are found, somehow i need to find the first 255 value in edges right 'above' the 2nd and 3th point, and the last 255 value next to the first point
i'm struggling too slice? the array, find the value 255, returns its index, so i can calculate the distance between point and plate.
any ideas on how to get the distance between?
Thank you in advance
I got it.
the code:
import sys
import cv2 as cv
import numpy as np
cap = cv.VideoCapture(0)
val = 50
singleprint = 0
# Dots per millimeter
dpmm = 2
def distance(circle):
# Calculating the distance np.where(array[row, column])
p = 0
if axis == 1:
p = np.where(edges[:,circle[0]] == 255)[0][0]
return (circle[1] - p - circle[2])/dpmm
else:
p = np.where(edges[circle[1],:] == 255)[0][-1]
return (p - circle[0] - circle[2])/dpmm
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
gray = cv.GaussianBlur(gray, (5,5), 0)
rows = gray.shape[0]
circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, 1, rows / 8,
param1=100, param2=30,
minRadius=1, maxRadius=30)
edges = cv.Canny(gray,val,val*3,apertureSize = 3)
lines = cv.HoughLines(edges,1.2,np.pi/180,200)
# Text property's
font = cv.FONT_HERSHEY_SIMPLEX
color = (255, 255, 255)
thickness = 2
index = 1
axis = 0
if len(circles[0]) > 2 :
circles = np.uint16(np.floor(circles))
circles2=sorted(circles[0],key=lambda x:x[0],reverse=False)
for i in circles2:
center = (i[0], i[1])
cv.circle(frame, center, 1, (0, 255, 0), 3)
text = str(distance(i))
cv.putText(frame, text, center, font, 1, color, thickness, cv.LINE_AA)
index += 1
axis = 1
cv.imshow("detected circles", frame)
if cv.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv.destroyAllWindows()
Key was learning to use Numpy in a specific row or column
np.where(edges[:,circle[0]] == 255)[0][0]
resource: https://youtu.be/GB9ByFAIAH4?t=1103
Hope this helps others.
Thanks all

HSV Range for Line Follower for various light conditions

I have the following problem: when detecting a while line under various lighting conditions, a mask (based on HSV) results in good performance in only one scenario (very bright or very shaded areas). As seen below.
My code is as follows, I am using HSV. The threshold for upper and lower is a constant value (+x/-x)
## SHADE
shadeLower1 = np.array([127,30,117] , dtype=np.uint8)
shadeUpper1 = np.array([147,51,138], dtype=np.uint8)
## SUN
sunLower2 = np.array([4,0,184], dtype=np.uint8)
sunUpper2 = np.array([104,57,255], dtype=np.uint8)
mask1 = cv2.inRange(hsv, shadeLower1, shadeUpper1)
mask2 = cv2.inRange(hsv, sunLower2, sunUpper2)
mask = cv2.max(mask1, mask2)
For instance, it will be fine in the shaded region (the white tape is perfect) and once it reaches the sunny area, the mask window is just saturated with white and I loose my white object.
Any help would be appreciated in what to do!
Shaded Area
Sunny Area
I mostly did the same thing you did for thresholding, but I used bitwise_and instead of bitwise_or (bitwise_or is the same as cv2.max). The lines are a little messy, but hopefully good enough for you to use. You might be able to clean them up more if you take the hue channel into account to exclude the red (I avoided it since white is technically all hues).
It might even be worth it to try and filter across multiple color spaces and combine the masks.
import cv2
import numpy as np
# find path and return its contour
def findPath(hsv):
# threshold on s an v channel
h,s,v = cv2.split(hsv);
mask1 = cv2.inRange(s, 0, 45);
mask2 = cv2.inRange(v, 115, 255);
mask3 = cv2.bitwise_and(mask1, mask2, mask = None);
# close
kernel = np.ones((5,5),np.uint8)
mask3 = cv2.dilate(mask3,kernel,iterations = 1);
mask3 = cv2.erode(mask3,kernel, iterations = 1);
# open
mask3 = cv2.erode(mask3,kernel,iterations = 1);
mask3 = cv2.dilate(mask3,kernel, iterations = 1);
# find contours
_, contours, _ = cv2.findContours(mask3, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE);
# find biggest contour
biggest = None;
biggest_size = -1;
for contour in contours:
area = cv2.contourArea(contour);
if area > biggest_size:
biggest = contour;
biggest_size = area;
return biggest;
# skeletonize the mask
def skeleton(mask):
# get structure
img = mask.copy();
size = np.size(img);
skel = np.zeros_like(mask);
elem = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3));
while True:
# skeleton iteration
eroded = cv2.erode(img,elem);
temp = cv2.dilate(eroded,elem);
temp = cv2.subtract(img,temp);
skel = cv2.bitwise_or(skel,temp);
# check for end condition
img = eroded.copy() ;
zeros = size - cv2.countNonZero(img);
if zeros == size:
break;
# connect small gaps
kernel = np.ones((2,2), np.uint8);
skel = cv2.dilate(skel, kernel, iterations = 1);
# filter out little lines
_, contours, _ = cv2.findContours(skel, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE);
# filter contours by size
big_cntrs = [];
for contour in contours:
perimeter = cv2.arcLength(contour, True);
if perimeter > 50:
big_cntrs.append(contour);
thin_lines = np.zeros_like(skel);
thin_lines = cv2.drawContours(thin_lines, big_cntrs, -1, 255, -1);
skel = thin_lines;
# dilate and close to connect lines
kernel = np.ones((3,3), np.uint8)
skel = cv2.dilate(skel, kernel, iterations = 5);
skel = cv2.erode(skel, kernel, iterations = 4);
# show
return skel;
# load image
imgs = [];
l1 = cv2.imread("line1.png");
l2 = cv2.imread("line2.png");
imgs.append(l1);
imgs.append(l2);
# convert
hsvs = [];
for img in imgs:
hsvs.append(cv2.cvtColor(img, cv2.COLOR_BGR2HSV));
# draw contours
masks = [];
for a in range(len(imgs)):
# get contour
contour = findPath(hsvs[a]);
# create mask
mask = np.zeros_like(hsvs[a][:,:,0]);
cv2.drawContours(mask, [contour], -1, (255), -1);
mask = cv2.medianBlur(mask, 5);
masks.append(mask);
# skeleton
skelly_masks = [];
for mask in masks:
skelly = skeleton(mask.copy());
skelly_masks.append(skelly);
# draw on original
for a in range(len(imgs)):
imgs[a][np.where(masks[a] == 255)] = (155,0,0); # 155 to avoid blinding people
imgs[a][np.where(skelly_masks[a] == 255)] = (0,0,155);
cv2.imshow(str(a), imgs[a]);
cv2.imwrite("img" + str(a) + ".png", imgs[a]);
cv2.waitKey(0);

Replace openCV face detection with MTCNN algorithm

I am using openCV for face detection. Sometimes, openCV makes an issue to detect faces. the function name is
def detectFace(img_path):
img = functions.detectFace(img_path)[0] #detectFace returns (1, 224, 224, 3)
return img[:, :, ::-1] #bgr to rgb
I want above output from MTCNN algorithm
detectFace function code
def detectFace(img, target_size=(224, 224), grayscale = False, enforce_detection = True):
img_path = ""
img = "/media/khawar/HDD_Khawar/Projects/" + img
print(img)
#-----------------------
exact_image = False
if type(img).__module__ == np.__name__:
exact_image = True
base64_img = False
if len(img) > 11 and img[0:11] == "data:image/":
base64_img = True
#-----------------------
opencv_path = get_opencv_path()
face_detector_path = opencv_path+"haarcascade_frontalface_default.xml"
eye_detector_path = opencv_path+"haarcascade_eye.xml"
if os.path.isfile(face_detector_path) != True:
raise ValueError("Confirm that opencv is installed on your environment! Expected path ",face_detector_path," violated.")
#--------------------------------
face_detector = cv2.CascadeClassifier(face_detector_path)
eye_detector = cv2.CascadeClassifier(eye_detector_path)
if base64_img == True:
img = loadBase64Img(img)
elif exact_image != True: #image path passed as input
if os.path.isfile(img) != True:
raise ValueError("Confirm that ",img," exists")
img = cv2.imread(img)
img_raw = img.copy()
#--------------------------------
faces = []
try:
faces = face_detector.detectMultiScale(img, 1.3, 5)
except:
pass
#print("found faces in ",image_path," is ",len(faces))
if len(faces) > 0:
print(faces[0])
x,y,w,h = faces[0]
detected_face = img[int(y):int(y+h), int(x):int(x+w)]
detected_face_gray = cv2.cvtColor(detected_face, cv2.COLOR_BGR2GRAY)
#---------------------------
#face alignment
eyes = eye_detector.detectMultiScale(detected_face_gray)
if len(eyes) >= 2:
#find the largest 2 eye
base_eyes = eyes[:, 2]
items = []
for i in range(0, len(base_eyes)):
item = (base_eyes[i], i)
items.append(item)
df = pd.DataFrame(items, columns = ["length", "idx"]).sort_values(by=['length'], ascending=False)
eyes = eyes[df.idx.values[0:2]]
#-----------------------
#decide left and right eye
eye_1 = eyes[0]; eye_2 = eyes[1]
if eye_1[0] < eye_2[0]:
left_eye = eye_1
right_eye = eye_2
else:
left_eye = eye_2
right_eye = eye_1
#-----------------------
#find center of eyes
left_eye_center = (int(left_eye[0] + (left_eye[2] / 2)), int(left_eye[1] + (left_eye[3] / 2)))
left_eye_x = left_eye_center[0]; left_eye_y = left_eye_center[1]
right_eye_center = (int(right_eye[0] + (right_eye[2]/2)), int(right_eye[1] + (right_eye[3]/2)))
right_eye_x = right_eye_center[0]; right_eye_y = right_eye_center[1]
#-----------------------
#find rotation direction
if left_eye_y > right_eye_y:
point_3rd = (right_eye_x, left_eye_y)
direction = -1 #rotate same direction to clock
else:
point_3rd = (left_eye_x, right_eye_y)
direction = 1 #rotate inverse direction of clock
#-----------------------
#find length of triangle edges
a = distance(left_eye_center, point_3rd)
b = distance(right_eye_center, point_3rd)
c = distance(right_eye_center, left_eye_center)
#-----------------------
#apply cosine rule
if b != 0 and c != 0: #this multiplication causes division by zero in cos_a calculation
cos_a = (b*b + c*c - a*a)/(2*b*c)
angle = np.arccos(cos_a) #angle in radian
angle = (angle * 180) / math.pi #radian to degree
#-----------------------
#rotate base image
if direction == -1:
angle = 90 - angle
img = Image.fromarray(img_raw)
img = np.array(img.rotate(direction * angle))
#you recover the base image and face detection disappeared. apply again.
faces = face_detector.detectMultiScale(img, 1.3, 5)
if len(faces) > 0:
x,y,w,h = faces[0]
detected_face = img[int(y):int(y+h), int(x):int(x+w)]
#-----------------------
#face alignment block end
#---------------------------
#face alignment block needs colorful images. that's why, converting to gray scale logic moved to here.
if grayscale == True:
detected_face = cv2.cvtColor(detected_face, cv2.COLOR_BGR2GRAY)
detected_face = cv2.resize(detected_face, target_size)
img_pixels = image.img_to_array(detected_face)
img_pixels = np.expand_dims(img_pixels, axis = 0)
#normalize input in [0, 1]
img_pixels /= 255
return img_pixels
else:
if (exact_image == True) or (enforce_detection != True):
if grayscale == True:
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img = cv2.resize(img, target_size)
img_pixels = image.img_to_array(img)
img_pixels = np.expand_dims(img_pixels, axis = 0)
img_pixels /= 255
return img_pixels
else:
print(img)
raise ValueError("Face could not be detected. Please confirm that the picture is a face photo or consider to set enforce_detection param to False.")
Try this out .
import mtcnn
import matplotlib.pyplot as plt
# load image from file
filename = "glediston-bastos-ZtmmR9D_2tA-unsplash.jpg"
pixels = plt.imread(filename)
print("Shape of image/array:",pixels.shape)
imgplot = plt.imshow(pixels)
plt.show()
# draw an image with detected objects
def draw_facebox(filename, result_list):
# load the image
data = plt.imread(filename)
# plot the image
plt.imshow(data)
# get the context for drawing boxes
ax = plt.gca()
# plot each box
for result in result_list:
# get coordinates
x, y, width, height = result['box']
# create the shape
rect = plt.Rectangle((x, y), width, height, fill=False, color='green')
# draw the box
ax.add_patch(rect)
# show the plot
plt.show()
# filename = 'test1.jpg' # filename is defined above, otherwise uncomment
# load image from file
# pixels = plt.imread(filename) # defined above, otherwise uncomment
# detector is defined above, otherwise uncomment
#detector = mtcnn.MTCNN()
# detect faces in the image
faces = detector.detect_faces(pixels)
# display faces on the original image
draw_facebox(filename, faces)
# draw the dots
for key, value in result['keypoints'].items():
# create and draw dot
dot = plt.Circle(value, radius=20, color='orange')
ax.add_patch(dot)
You are using detectFace function within deepface? It currently wraps opencv, ssd, dlib and mtcnn to detect and align faces.
def detectFace(img_path):
backends = ['opencv', 'ssd', 'dlib', 'mtcnn']
img = functions.detectFace(img_path, detector_backend = backends[3])[0] #detectFace returns (1, 224, 224, 3)
return img[:, :, ::-1] #bgr to rgb
The result of the detectFace function is detected and aligned with mtcnn now.
Besides, you can run face recognition with mtcnn backend as well.
from deepface import DeepFace
obj = DeepFace.verify("img1.jpg", "img2.jpg", detector_backend = 'mtcnn')

Remove coins shadow using opencv

I am trying to count how many coins there are in the image using the latest version of OpenCV, but I am struggling with the shadows.
The Canny Edge detector method is being used but as you can see in the second image, it is not working as expected because of the shadows... Any ideas about how I could deal with this problem?
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)
median = np.median(image)
lower = int(max(0, 0.67 * median))
upper = int(min(255, (1.33) * median))
canny = cv2.Canny(blurred, lower, upper)
contours, hierachy = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
coins = cv2.drawContours(image, contours, -1, (0, 255, 0), 2)
cv2.imshow("Coins", coins)
You can use the coin selection by color.
import cv2 as cv
import numpy as np
low_H = 0
low_S = 50
low_V = 0
high_H = 255
high_S = 255
high_V = 255
frame = cv.imread('PzB9I.png')
frame_HSV = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
frame_threshold = cv.inRange(frame_HSV, (low_H, low_S, low_V), (high_H, high_S, high_V))
# filling holes
im_floodfill = frame_threshold.copy()
h, w = frame_threshold.shape[:2]
mask = np.zeros((h+2, w+2), np.uint8)
cv.floodFill(im_floodfill, mask, (0,0), 255);
im_floodfill_inv = cv.bitwise_not(im_floodfill)
mask = frame_threshold | im_floodfill_inv
# find contours
contours, hierachy = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
coins = cv.drawContours(frame, contours, -1, (0, 255, 0), 1)
cv.imshow("Coins", coins)

Resources