When i try to detect face using my laptop or computer web cam it work fine but when i try to detect using IP cam it looks like it take to much time to detect one frame. Is there any solution for this because I also try YOLO. It take more time than opencv haar cascade
There I have a simple code that detect face and crop than part of frame.
cap = cv2.VideoCapture("web_Cam_IP")
cropScal = 25
while(True):
# Capture frame-by-frame
for i in range(10): #this loop skip 10 frames if I don't skip frame it looks like it stack there
ret, frame = cap.read()
frame = cv2.resize(frame, (0, 0), fx=0.70, fy=0.70)
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
faces = faceCascade.detectMultiScale(gray, scaleFactor=1.02, minNeighbors=5, minSize=(30, 30))
for (x, y, w, h) in faces:
if len(faces) > 0 :
try:
img = gray[y-cropScal:y+h+cropScal, x-cropScal:x+w+cropScal]
img = cv2.resize(img,(200,200))
img = Image.fromarray(img)
img.save('images/'+datetime.now().strftime("%d_%m_%Y_%I_%M_%S_%p")+'.png')
except Exception as e:
pass
cv2.rectangle(gray, (x-cropScal, y-cropScal), (x+w+cropScal, y+h+cropScal), (0, 255, 0), 2)
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
You're only scaling the input frames by a factor of 0.70, not to an absolute resolution. It's possible that your IP cam has a higher resolution than your webcam and so the detection requires more time to analyze a larger frame.
Try rescaling the frames to a definite size (eg. 800x600) before the face detection.
Related
I am trying to detect faces in a camera recorded video. When i did it with webcam video, it's working fine. But, with camera recorded video, the video gets rotated by -90 degree. Please suggest me, how do I get the actual video output for face detection?
import cv2
import sys
cascPath = sys.argv[1]
faceCascade = cv2.CascadeClassifier('C:/Users/HP/Anaconda2/pkgs/opencv-3.2.0-np112py27_204/Library/etc/haarcascades/haarcascade_frontalface_default.xml')
#video_capture = cv2.videoCapture(0)
video_capture = cv2.VideoCapture('C:/Users/HP/sample1.mp4')
w=int(video_capture.get(3))
h=int(video_capture.get(4))
#output = cv2.VideoWriter('output_1.avi',cv2.VideoWriter_fourcc('M','J','P','G'), 60,frameSize = (w,h))
while True:
ret, frame = video_capture.read()
frame = rotateImage(frame,90)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(gray, 1.3, 5)
# Draw a rectangle around the faces
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
#cv2.imshow('face',i)
#output.write(frame)
cv2.imshow('Video', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
video_capture.release()
output.release()
cv2.destroyAllWindows()
In cv2 you can use the cv2.rotate function to rotate image as per your requirement
rotated=cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)
for rotating video you can use cv2.flip(), this method take 3 Args and one of them is the rotating code(0,1,-1) you can check this link for more details:
https://www.geeksforgeeks.org/python-opencv-cv2-flip-method/
I want to read a video and detect the faces by cutting it into frames. But, it did not work well and I don't understand where the problem is. Could you help me fix it please.
NB :: I work with google collaboratory and I detect the faces with the library face_recognition.
import face_recognition
import cv2
from google.colab.patches import cv2_imshow
input_video = cv2.VideoCapture('/content/My Drive/video-3.mp4')
# Metadata from the input video
frames_per_second = int(input_video.get(cv2.CAP_PROP_FPS))
frame_width = int(input_video.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(input_video.get(cv2.CAP_PROP_FRAME_HEIGHT))
print('Metadata from input video:',
'\nFrames per second:', frames_per_second,
'\nFrame width:', frame_width,
'\nFrame height:', frame_height)
codec = cv2.VideoWriter.fourcc(*'XVID')
video_writer = cv2.VideoWriter('output_video.mp4',
codec,
frames_per_second,
(frame_width, frame_height))
# An array to hold the locations of faces that are detected on individual frames
face_locations = []
# A counter to keep track of the number of frames processed
count = 1
# Loop through all the frames in the video
while (count != no_of_frames):
# Read the video to retrieve individual frames. 'frame' will reference the inidivdual frames read from the video.
ret, frame = input_video.read()
# Check the 'ret' (return value) to see if we have read all the frames in the video to exit the loop
if not ret:
print('Processed all frames')
break
# Convert the image (frame) to RGB format as by default Open CV uses BGR format.
# This conversion is done as face_recognition and other libraries usually use RGB format.
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Get the coordinates in the image where a face is detected. Use the model 'cnn' after greater accuracy.
face_locations = face_recognition.face_locations(rgb_frame, model='cnn')
# Loop through the face locations array and draw a rectangle around each face that is detected in the frame
for top, right, bottom, left in face_locations:
cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
# Write the frame to the output vide0
video_writer.write(frame)
# Print for every 50 frames processed
if(count % 50 == 0):
print('Processed', count, 'frames')
count += 1
# Release to close all the resources that we have opened for reading and writing video
input_video.release()
video_writer.release()
cv2.destroyAllWindows()
The result:
in line 7: name 'no_of_frames' is not defined
Here it is the complete code
import face_recognition
import cv2
from google.colab.patches import cv2_imshow
input_video = cv2.VideoCapture('/content/My Drive/video-3.mp4')
# Metadata from the input video
frames_per_second = int(input_video.get(cv2.CAP_PROP_FPS))
frame_width = int(input_video.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(input_video.get(cv2.CAP_PROP_FRAME_HEIGHT))
print('Metadata from input video:',
'\nFrames per second:', frames_per_second,
'\nFrame width:', frame_width,
'\nFrame height:', frame_height)
codec = cv2.VideoWriter.fourcc(*'XVID')
video_writer = cv2.VideoWriter('output_video.mp4',
codec,
frames_per_second,
(frame_width, frame_height))
# An array to hold the locations of faces that are detected on individual frames
face_locations = []
# A counter to keep track of the number of frames processed
count = 1
# Loop through all the frames in the video
while (count != no_of_frames):
# Read the video to retrieve individual frames. 'frame' will reference the inidivdual frames read from the video.
ret, frame = input_video.read()
# Check the 'ret' (return value) to see if we have read all the frames in the video to exit the loop
if not ret:
print('Processed all frames')
break
# Convert the image (frame) to RGB format as by default Open CV uses BGR format.
# This conversion is done as face_recognition and other libraries usually use RGB format.
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Get the coordinates in the image where a face is detected. Use the model 'cnn' after greater accuracy.
face_locations = face_recognition.face_locations(rgb_frame, model='cnn')
# Loop through the face locations array and draw a rectangle around each face that is detected in the frame
for top, right, bottom, left in face_locations:
cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
# Write the frame to the output vide0
video_writer.write(frame)
# Print for every 50 frames processed
if(count % 50 == 0):
print('Processed', count, 'frames')
count += 1
# Release to close all the resources that we have opened for reading and writing video
input_video.release()
video_writer.release()
cv2.destroyAllWindows()
You have not declared a 'no_of_frames' variable. Simple as that.
Here's sample code that accomplishes the same task.
capture = cv2.VideoCapture(0)
while 1:
_, image = capture.read()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
cv2.circle(image,(x+int(w/2),y+int(h/2)),(int(h)),(255,0,0),4)
roi_gray = gray[y:y+h, x:x+w]
roi_color = image[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(roi_gray)
for (ex,ey,ew,eh) in eyes:
cv2.circle(roi_color, (ex + int(ew/2), ey + int(eh/2)), (int(eh/2)), (0,0,255), 2)
cv2.imshow('Image', image)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
# Close the window
capture.release()
# De-allocate any associated memory usage
cv2.destroyAllWindows()
camera = webcam; % Connect to the camera
nnet = alexnet; % Load the neural net
while true
picture = camera.snapshot; % Take a picture
picture = imresize(picture,[227,227]); % Resize the picture
label = classify(nnet, picture); % Classify the picture
image(picture); % Show the picture
title(char(label)); % Show the label
drawnow;
end
I found this matlab code in the internet. It displays a window with the picture from a webcam and very quickly also names the things in the picture ("keyboard","bootle","pencil","clock"...). I want to do that in python.
So far I have this:
import cv2
import sys
faceCascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
video_capture = cv2.VideoCapture(0)
while True:
ret, frame = video_capture.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30),
flags=cv2.cv.CV_HAAR_SCALE_IMAGE
)
# Draw a rectangle around the faces
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
cv2.imshow('Video', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
This is alreay very similar, but only detecting faces. The matlab code uses alexnet. I guess this is a pre-trained network based on imagenet data (http://www.image-net.org/). But it is no longer available.
How would I do this in python?
(There has been a similar question here, but it is 4 yrs. old and I think there are newer techniques now).
With the "tensorflow" package and the pre-trained network "vgg16", the solution is quite easy.
See https://github.com/machrisaa/tensorflow-vgg/blob/master/test_vgg16.py
There is a code that detects faces in video file while displaying it frame by frame:
cap = cv2.VideoCapture(videoPath)
faceCascade = cv2.CascadeClassifier(cascPath)
while (cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30),
flags=cv2.CASCADE_SCALE_IMAGE
)
# Draw a rectangle around the faces
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x+w, y+h), (233, 153, 22), 2)
# Display the resulting frame
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
I need a code that can give you periods of time when a face is detected and periods of time when a face is not detected. Can somebody help me with that? At least some tips how to solve this problem, where to look etc..
Keep track of the timestamp of current frame, previous frame, and the starting frame of the current sequence containing faces.
Once you no longer detect a face in a frame, append a pair (starting, previous) to a list.
import time
# ....
def get_timestamp():
# Make the timestamp whatever you want...
return time.strftime("%Y%m%d-%H%M%S")
# ....
face_present = []
ts_start = None
ts_prev = None
# ....
while (cap.isOpened()):
ret, frame = cap.read()
ts = get_timestamp()
# ....
if len(faces) > 0: # Some faces detected
if ts_start is None: # This is the start of current sequence
ts_start = ts
elif (ts_start is not None) and (ts_prev is not None):
# First frame without face following a sequence with face...
face_present.append((ts_start, ts_prev))
ts_start = None
ts_prev = ts
You could make the timestamp whatever you want, could even be a frame number if that's what you're after.
Same approach can be used to determine the times when face is not present, you only need to change the condition of the first if statement.
I'm using a guide provided online with opencv2.4 that shows you how to detect faces with opencv2 and python. I followed the guide and understand what it says. However I can't seem to find the issue with my program because the video shows but now face is detected and the video is very clear. There are no errors. I ran in debug mode and the value faces remains a blank tuple so I'm assuming that means its not finding the face. What I don't understand is why and I think it has something to do with the hash table.
By hash table I mean the cascade xml file. I understand cascades are basically the guidelines for detecting the facial artifacts correct?
Links to the guides. The hash table i.e the xml file is on the github linked.
https://github.com/shantnu/FaceDetect/blob/master/haarcascade_frontalface_default.xml
https://realpython.com/blog/python/face-detection-in-python-using-a-webcam/
import cv2
import sys
import os
#cascPath = sys.argv[1]
cascPath = os.getcwd()+'facehash.xml'
faceCascade = cv2.CascadeClassifier(cascPath)
print faceCascade
video_capture = cv2.VideoCapture(0)
while True:
# Capture frame-by-frame
ret, frame = video_capture.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30),
flags=cv2.cv.CV_HAAR_SCALE_IMAGE
)
cv2.cv
# Draw a rectangle around the faces
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
# Display the resulting frame
cv2.imshow('Video', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything is done, release the capture
video_capture.release()
cv2.destroyAllWindows()
You have a wrong path to your xml classifier. (I guess you've changed the name to get a shorter form).
Instead of your cascPath:
cascPath = os.getcwd()+'facehash.xml'
Try this:
cascPath = "{base_path}/folder_with_your_xml/haarcascade_frontalface_default.xml".format(
base_path=os.path.abspath(os.path.dirname(__file__)))
And now it should work as well.