Detect if a object is big enough open cv - python

I need some help here plz :)
I have this piece of code with open cv:
import cv2
import numpy as np
import time
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
low_red = np.array([100, 100, 100])
high_red = np.array([225, 225, 225])
mask = cv2.inRange(frame, low_red, high_red)
hasColor = np.sum(mask)
if hasColor > 1000000:
print(f'Hand opened, infos : {hasColor}')
elif hasColor > 500000 and hasColor < 1000000:
print(f'Hand closed, infos : {hasColor}')
cv2.imshow("Camera", frame)
cv2.imshow("Mask", mask)
if cv2.waitKey(1) & 0xFF == ord('e'):
break
And I would like that it detect only the objects of a certain size (like a hand) and not the smaller ones.
Thanks for help :)
EDIT: Made some good progress but still don't know how to get the size
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
low = np.array([100, 100, 100])
high = np.array([225, 225, 225])
mask = cv2.inRange(frame, low, high)
cv2.imshow("Camera", frame)
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
ret, tresh = cv2.threshold(gray, 127, 255, 0)
contours, hierarchy = cv2.findContours(tresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
x,y,w,h = cv2.boundingRect(contours[i])
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow("Mask", mask)
cv2.imshow("Hull", frame)
if cv2.waitKey(1) & 0xFF == ord('e'):
break
So I think I have to get the value of the bounding box but idk how

Problem solved thanks to a kind human,
I just had to add the following code in the for loop:
if h > 150 and w > 150:
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
I just had to check for the size, thanks for your help !

Related

How do I add an image overlay to my live video using cv2?

This is my code, I've looked at some tutorials but can't find what I'm looking for
I want to overlay the Frame.png image on my webcam. I tried to add the image directly but it didn't work either. If possible, Is there a way to add an image, not to overlay but to keep the image at a certain coordinate in the live webcam window
import cv2
import numpy as np
def detect_and_save():
alpha = 0.2
beta = 1-alpha
cap = cv2.VideoCapture(0)
sciframe = cv2.imread('Frame.png')
classifier = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
while True:
ret ,frame = cap.read()
overlay = frame.copy()
output = frame.copy()
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
faces = classifier.detectMultiScale(gray,1.5,5)
cv2.putText(output, "HUD Test",(175, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 50, 50), 3)
cv2
for face in faces:
x,y,w,h = face
cv2.rectangle(overlay,(x,y),(x+w,y+h),(255,200,0),-1)
cv2.rectangle(overlay,(x,y),(x+w,y+h),(255,0,0),1)
cv2.rectangle(overlay,(x,y-20),(x+w,y),(25,20,0),-1)
cv2.addWeighted(overlay,alpha,output,beta,0,output)
cv2.putText(output,"Human",(x+10,y-10),cv2.FONT_HERSHEY_SIMPLEX,
0.35, (0, 0, 255), 1)
if not ret:
continue
cv2.imshow("HUD",output)
key = cv2.waitKey(1)
if key == ord('q'):
break
elif key == ord('s'):
cv2.imwrite('./images/CID_{}.png'.format(time.strftime('%d%m%y_%H_%M_%S')),output)
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
import time
detect_and_save()
You can directly add one image on top of another one at any coordinate easily in opencv.
cap = cv2.VideoCapture(0)
im_height = 50 #define your top image size here
im_width = 50
im = cv2.resize(cv2.imread("Frame.png"), (im_width, im_height))
while (True):
ret, frame = cap.read()
frame[0:im_width, 0:im_height] = im #for top-left corner, 0:50 and 0:50 for my image; select your region here like 200:250
cv2.imshow("live camera", frame)
if cv2.waitKey(1) == ord("q"):
break
cap.release()
cv2.destroyAllWindows()

Optimised way to generate summary of a video?

The code which I have written is able to create the summary of the video by skippig the frames with no motion. But it is taking more than 10 times the duration of the video to save the output video. So anyone can please help me with making some changes in the code. It is not the issue with system configuration. I have tried it even in a i7 GPU system.
import cv2
import imutils
vs = cv2.VideoCapture("example_01.mp4")
fgbg = cv2.createBackgroundSubtractorMOG2()
pathOut = "output.mp4"
frame_array = []
while True:
ret,frame = vs.read()
forig = frame.copy()
height,width,layers = frame.shape
size = (width,height)
blurred = cv2.GaussianBlur(frame, (11, 11), 0)
gray = cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY)
mask = fgbg.apply(gray)
mask = cv2.erode(mask, None, iterations=2)
mask = cv2.dilate(mask, None, iterations=2)
cnts = cv2.findContours(mask.copy(),
cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cv2.imshow('mask',mask)
for c in cnts:
area = cv2.contourArea(c)
if area > 2000:
frame_array.append(frame)
out = cv2.VideoWriter(pathOut,cv2.VideoWriter_fourcc(*'MPEG'), 20,
size)
for i in range(len(frame_array)):
out.write(frame_array[i])
out.release()
cv2.imshow("Frame", frame)
key = cv2.waitKey(25)
if key == ord("q"):
break
vs.release()
cv2.destroyAllWindows()
I took 18seconds movie and your code on my old computer worked many minutes and it was slowing down so finally I killed it and didn't get output movie.
This code needs ~57 seconds to do the same. If I don't display windows then it needs 39 seconds.
I open out only once. I don't append frame to frame_array but write this one frame directly to file.
import cv2
import imutils
import time
vs = cv2.VideoCapture("Wideo/1-sierpinski-carpet-turtle.mp4")
fgbg = cv2.createBackgroundSubtractorMOG2()
pathOut = "output.mp4"
out = None
start = time.time()
while True:
ret, frame = vs.read()
if frame is None:
break
forig = frame.copy()
height, width, layers = frame.shape
size = (width, height)
if not out:
out = cv2.VideoWriter(pathOut,cv2.VideoWriter_fourcc(*'MPEG'), 20, size)
blurred = cv2.GaussianBlur(frame, (11, 11), 0)
gray = cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY)
mask = fgbg.apply(gray)
mask = cv2.erode(mask, None, iterations=2)
mask = cv2.dilate(mask, None, iterations=2)
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cv2.imshow('mask',mask)
for c in cnts:
area = cv2.contourArea(c)
if area > 2000:
out.write(frame)
break # don't check other areas
cv2.imshow("Frame", frame)
key = cv2.waitKey(25)
if key == ord("q"):
break
end = time.time()
print("time:", end-start)
out.release()
vs.release()
cv2.destroyAllWindows()
Your code opens file again and again and write all frames again and again - so it was slowing down on my computer. You could eventually write it only once after loop.
import cv2
import imutils
import time
vs = cv2.VideoCapture("Wideo/1-sierpinski-carpet-turtle.mp4")
fgbg = cv2.createBackgroundSubtractorMOG2()
pathOut = "output.mp4"
frame_array = []
start = time.time()
while True:
ret, frame = vs.read()
if frame is None:
break
forig = frame.copy()
height, width, layers = frame.shape
size = (width, height)
blurred = cv2.GaussianBlur(frame, (11, 11), 0)
gray = cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY)
mask = fgbg.apply(gray)
mask = cv2.erode(mask, None, iterations=2)
mask = cv2.dilate(mask, None, iterations=2)
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cv2.imshow('mask',mask)
for c in cnts:
area = cv2.contourArea(c)
if area > 2000:
frame_array.append(frame)
break
cv2.imshow("Frame", frame)
key = cv2.waitKey(25)
if key == ord("q"):
break
# --- after loop ---
out = cv2.VideoWriter(pathOut,cv2.VideoWriter_fourcc(*'MPEG'), 20, size)
for frame in frame_array:
out.write(frame)
out.release()
end = time.time()
print("time:", end-start)
vs.release()
cv2.destroyAllWindows()

Reading a video file VideoCapture

Why is it if i read a video file using cv2.VideoCapture('video.avi') the fps is very very very low? I want the fps to be the same as when i play the video using a video player(30fps). What changes should i make to achieve this? Btw, i am using a raspberry pi 3 with python.
import cv2
import numpy as np
cap = cv2.VideoCapture('Fchecking.avi')
kernel = np.ones((5,5), np.uint8)
while(1):
# Take each frame
ret, frame = cap.read()
img2gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
ret,mask = cv2.threshold(img2gray,140,255,cv2.THRESH_BINARY)
w3w = cv2.adaptiveThreshold(mask,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,47,2)
cv2.imshow("mask", mask)
mask_inv = cv2.bitwise_not(w3w)
img2_fg = cv2.bitwise_and(frame, frame, mask=mask_inv)
hsv = cv2.cvtColor(img2_fg, cv2.COLOR_BGR2HSV)
lower_red= np.array([0,58,130])
upper_red = np.array([255,255,255])
erosion = cv2.erode(mask,kernel,iterations = 3)
rmask = cv2.inRange(hsv, lower_red, upper_red)
mask2 = cv2.morphologyEx(rmask, cv2.MORPH_CLOSE, kernel)
final = cv2.bitwise_and(frame, frame, mask=mask2)
cv2.imshow('final',final)
cv2.imshow('original',frame)
k = cv2.waitKey(5) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
Why is it if i read a video file using cv2.VideoCapture('video.avi') the fps is very very very low?
The answer to this question is the massive chunk of code that you have between reading the frame and showing it to the screen. When you watch the video in a standard video player it doesnt do this processing.
img2gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
ret,mask = cv2.threshold(img2gray,140,255,cv2.THRESH_BINARY)
w3w = cv2.adaptiveThreshold(mask,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,47,2)
cv2.imshow("mask", mask)
mask_inv = cv2.bitwise_not(w3w)
img2_fg = cv2.bitwise_and(frame, frame, mask=mask_inv)
hsv = cv2.cvtColor(img2_fg, cv2.COLOR_BGR2HSV)
lower_red= np.array([0,58,130])
upper_red = np.array([255,255,255])
erosion = cv2.erode(mask,kernel,iterations = 3)
rmask = cv2.inRange(hsv, lower_red, upper_red)
mask2 = cv2.morphologyEx(rmask, cv2.MORPH_CLOSE, kernel)
final = cv2.bitwise_and(frame, frame, mask=mask2)
What changes should i make to achieve this?
It's likely that:
If you reduce the processing it will speed up
If you increase the processing power it will speed up

Threshold + Contours (video)

Basically, my program will detect moving objects in the video scene by using a method called (thresholding). But, i want to add findcontours feature into the program. I built this code from scratch. Now im stuck at 'findcontours' and 'drawcontours' part.
Problem:
Cant draw contours on detected objects (fixed)
ValueError: too many values to unpack (findcontours)
This is my code:
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
history = 150
varThreshold = 18
fgbg = cv2.createBackgroundSubtractorMOG2()
while(1):
ret, frame = cap.read()
fgmask = fgbg.apply(frame)
fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
img_,contours, hierarchy = cv2.findContours(fgmask, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.imshow('frame',fgmask)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
cap.release()
cv2.destroyAllWindows()

Finding circles in a live video feed using python 2.7.11and opencv 3.0.0

I need help finding circles in a live video feed from my webcam. I just need feedback from python that a circle has or has not been detected. Also what is the best method for finding the size of the circle in pixels for better detection. My code so far
import cv2
import numpy as np
import sys
cap = cv2.VideoCapture(0)
while(True):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.medianBlur(gray,5)
cimg = frame.copy()
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 10, np.array([]), 200, 100, 100, 200)
if circles == 1:
print('Circle true')
else:
print('No circle')
cv2.imshow('video',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
There it is !
import cv2
import numpy as np
import sys
cap = cv2.VideoCapture(0)
while(True):
gray = cv2.medianBlur(cv2.cvtColor(cap.read()[1], cv2.COLOR_BGR2GRAY),5)
cirles=cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 10)# ret=[[Xpos,Ypos,Radius],...]
if cirles!=None:print "Circle There !"
cv2.imshow('video',gray)
if cv2.waitKey(1)==27:# esc Key
break
cap.release()
cv2.destroyAllWindows()

Categories

Resources