I have to detect faces using openCV and python. Then identify the position of the detected face if it is in the right, the left or the middle of the screen.
I already succeed to detect faces using the code below and still to know the position of the faces could someone please help me ?
import cv2
import sys
import numpy as np
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
cap = cv2.VideoCapture(1)
while True:
#capture frame by frame
ret,frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.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
cap.release()
cv2.destroyAllWindows()
You could get the centre of the rectangle:
centre_x = x + w/2
centre_y = y + y/2
Then compare it with the size of the image. Assuming you have the image shape information:
height, width, channels = frame.shape #it could be gray.shape too
You can understand for example if the face is detected on the left side of the image by checking centre_x<width.
You have all the information to divide the image into a grid and understand where the rectangle places itself.
Related
I successfully displayed the video feed and am trying to change the background color of the area outside ROI from black to blue but the screen still shows black background. Please help me solve the problem. Any help would be greatly appreciated.
Original code
import numpy as np
from cv2 import cv2
'''
ML object detection algo(haarcascade)used to identify objects.
the XML file consists of trained Haar Cascade models.
'''
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
#initialize video from the webcam
video = cv2.VideoCapture(1)
while True:
# ret tells if the camera works properly. Frame is an actual frame from the video feed
ret, frame= video.read()
# print(cv2.VideoCapture(0).isOpened())
# make sure port is working and read the image
if frame is not None and video.isOpened():
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Detect the faces within the subregions of the image in scales
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=6)
# Draw the rectangle around each face
for (x, y, w, h) in faces:
#Use the coordinates to find the center of the face and from that point draw a rectangle of radius w/2 or h/2.
center_coordinates = x + w // 2, y + h // 2
radius = w // 2 # or can be h / 2 or can be anything based on your requirements
#background color(black)
mask=np.zeros(frame.shape[:2] , dtype="uint8")
# Draw the desired region to crop out in white
cv2.circle(mask, center_coordinates, radius, (255,255,255),-1)
masked=cv2.bitwise_and(frame,frame,mask=mask)
cv2.imshow('mask applied',masked)
if cv2.waitKey(30) & 0xff==27:
break
video.release()
cv2.destroyAllWindows()
The above code detects and displays the face in the circular mask on the black background. But as mentioned above, The background color outside circular ROI should be blue.
I tried replacing mask=np.zeros(frame.shape[:2], dtype="uint8")with the code below and fails. Frame.shape[0:2]doesn't even include channel and I can't figure out how to change the color in the first place.
mask=np.ones(frame.shape[0:2], dtype="uint8")
mask[:,:,0]=255
mask[:,:,1]=0
mask[:,:,2]=0
I also tried creating a circular masked image then place it on another image only to find out it results in the same problem.
import numpy as np
from cv2 import cv2
'''
ML object detection algo(haarcascade)used to identify objects.
the XML file consists of trained Haar Cascade models.
'''
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
#initialize video from the webcam
video = cv2.VideoCapture(1)
print(cv2.VideoCapture(1).isOpened())
while True:
# ret tells if the camera works properly. Frame is an actual frame from the video feed
ret, frame= video.read()
# print(cv2.VideoCapture(0).isOpened())
# make sure port is working and read the image
if frame is not None and video.isOpened():
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Detect the faces within the subregions of the image in scales
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=6)
# Draw the rectangle around each face
for (x, y, w, h) in faces:
#Use the coordinates to find the center of the face and from that point draw a rectangle of radius w/2 or h/2.
center_coordinates = x + w // 2, y + h // 2
radius = w // 2 # or can be h / 2 or can be anything based on your requirements
#background color(black)
mask=np.zeros(frame.shape[:2] , dtype="uint8")
# create blue colored background
color = np.full_like(frame, (255,0,0))
# Draw the desired region to crop out in white
roi=cv2.circle(mask, center_coordinates, radius, (255,255,255),-1)
masked=cv2.bitwise_and(frame,frame,mask=mask)
mask_blue=cv2.bitwise_and(color,color,mask=mask-roi)
# combine the two masked images
result = cv2.add(masked,mask_blue)
cv2.imshow('result',result)
if cv2.waitKey(30) & 0xff==27:
break
video.release()
cv2.destroyAllWindows()
I have changed your code as follows according to your requirement. Here i have added an extra line
masked[np.where((masked==[0,0,0]).all(axis=2))]=[255,0,0]
where you can change pixel values of black region to any specific color.
import numpy as np
import cv2
'''
ML object detection algo(haarcascade)used to identify objects.
the XML file consists of trained Haar Cascade models.
'''
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades +'haarcascade_frontalface_default.xml')
#initialize video from the webcam
video = cv2.VideoCapture(0)
print(cv2.VideoCapture(0).isOpened())
while True:
# ret tells if the camera works properly. Frame is an actual frame from the video feed
ret, frame= video.read()
# print(cv2.VideoCapture(0).isOpened())
# make sure port is working and read the image
if frame is not None and video.isOpened():
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Detect the faces within the subregions of the image in scales
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=6)
# Draw the rectangle around each face
for (x, y, w, h) in faces:
#Use the coordinates to find the center of the face and from that point draw a rectangle of radius w/2 or h/2.
center_coordinates = x + w // 2, y + h // 2
radius = w // 2 # or can be h / 2 or can be anything based on your requirements
#background color(black)
mask=np.zeros(frame.shape[:2] , dtype="uint8")
# Draw the desired region to crop out in white
roi=cv2.circle(mask, center_coordinates, radius, (255,255,255),-1)
masked=cv2.bitwise_and(frame,frame,mask=mask)
masked[np.where((masked==[0,0,0]).all(axis=2))]=[255,0,0]
cv2.imshow('result',masked)
if cv2.waitKey(30) & 0xff==27:
break
video.release()
cv2.destroyAllWindows()
I have code that detects a face. All I want to do is save the detected face as a jpg
Here is the code for my program:
import numpy as np
import cv2
detector= cv2.CascadeClassifier('haarcascade_fullbody.xml')
cap = cv2.VideoCapture(0)
while(True):
ret, img = cap.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = detector.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
cv2.imshow('frame',img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
How do I save the detected face? Please help!
detectMultiScale method returns a list where each elements contains the coordinates and width and height of each face that is detected.
So you can use cv2.imwrite and array slicing:
count = 0
for (x,y,w,h) in faces:
face = img[y:y+h, x:x+w] #slice the face from the image
cv2.imwrite(str(count)+'.jpg', face) #save the image
count+=1
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
I'm trying to record the distance travelled by an object (in this instance, part of a face as detected by a haar cascade) from a video file. So far, I have a rectangle drawn to the section of the face that I wish to record x/y travel data for, but have been unable to find info on exactly how to store info on how far/which way the face has travelled in 2 dimensions. My code is below:
import cv2
import numpy as py
from matplotlib import pyplot as plt
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
cap = cv2.VideoCapture("resources/video/EXAMPLE.mp4")
while True:
ret, img = cap.read()
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 9)
for (x,y,w,h) in faces:
cv2.rectangle(img, (x,y), (x+w, int(y+h/3)), (255,0,0), 2)
cv2.imshow('img',img)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
cap.release()
cap.destroyAllWindows()
Any info/pointers as far as how I can record movement data would be appreciated!
If you simply want to store the coordinates, you can add the (x,y) tuple to a list
If you're tracking just one face you could use object tracking
If you want to track multiple faces you can check out the multitracker.
I've used the below code. However, I'm able to take control of the faces in the webcam. However, how to fetch the closest image to the camera. Can anyone help ?
import cv2
import numpy as np
import time
face_cascade = cv2.CascadeClassifier('C:\\Users\\Admin\\Desktop\\opencv\\opencv\\data\\haarcascades\\haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('C:\\Users\\Admin\\Desktop\\opencv\\opencv\\data\\haarcascades\\haarcascade_eye.xml')
cap = cv2.VideoCapture(0)
while True:
ret,img = cap.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3,5)
print len(faces)
for(x,y,w,h) in faces:
crop_img = img[y: y + h, x: x + w] #Crop from x, y, w, h->100, 200, 300, 400
ts = time.time()
'cv2.imwrite("C:\\Users\\Admin\\Desktop\\opencv\\detectedfaces\\"+str(ts)+".jpg", crop_img)'
cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0), 2)
roi_gray = gray[y:y+h,x:x+h]
roi_color = img[y:y+h,x:x+h]
eyes = eye_cascade.detectMultiScale(roi_gray)
for(ex,ey,ew,eh) in eyes:
cv2.rectangle(roi_color, (ex,ey), (ex+ew,ey+eh), (0,255,0), 2)
cv2.imshow('img',img)
time.sleep(5)
k = cv2.waitKey(1) & 0xFF == ord('q')
if k == 27:
break;
cap.release()
cv2.destroAllWindows()
Since you have the eye locations, I'd just use IOD (inter-ocular distance). Basically the distance between the center of your two eye ROIs. That metric could be used to infer distance from the camera.
Something like this will do the job:
if len(eyes) >= 2:
IOD = abs((eyes[0][0] + eyes[0][1] / 2.0) - (eyes[1][0] + eyes[1][1] / 2.0))
cv2.putText(img,'%d'%IOD, (30,30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 1)
It won't be terribly accurate if two people are at roughly the same distance from the camera, but I don't think much will. You could also correlate facial width and IOD to compensate for people with different sized heads.
I need to find the centre of a rectangle that gets put around a face when it's detected in OpenCV. I am using Python in Visual Studio.
Here is the code I am running:
#!/usr/bin/env python
from cv2 import *
import sys
cascPath = sys.argv[1]
faceCascade = CascadeClassifier(cascPath)
video_capture = VideoCapture(0)
while True:
# Capture frame-by-frame
ret, frame = video_capture.read()
gray = cvtColor(frame, COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30),
flags=CASCADE_SCALE_IMAGE
)
# Draw a rectangle around the faces
for (x, y, w, h) in faces:
rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
font = FONT_HERSHEY_SIMPLEX
# Draw text on the frame
putText(frame, 'Hayden' ,(10,100), font, 2,(255,255,255),2,LINE_AA)
# Display the resulting frame
imshow('Video', frame)
if waitKey(1) & 0xFF == ord('q'):
break
# When everything is done, release the capture
video_capture.release()
destroyAllWindows()
All I want to do is find the centre of the rectangle, any help will be greatly appreciated!
I'm really sorry but I don't know python. The code for this in C++ is:
Point center = Point(rectangle.x + rectangle.width)/2, (rectangle.y + rectangle.height)/2);
I'd be surprised if this didn't translate almost exactly to python