I have successfully detected faces, save cropped face in a folder. Then view the total count of detected faces on the video using cv2.puttext.
Now I want to show each cropped face on the video just like I am showing the total count.
The code is as follows:
import numpy as np
import cv2
import time
from time import strftime
num = 0
total = 0
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
cap = cv2.VideoCapture(0)
previous_millis = 0
while 1:
ret, img = cap.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img,'Person Count Algorithm',(10,50), font, 1,(255,0,0),2,cv2.LINE_AA)
S1=int(strftime("%S"))
#print "timing"
#print(S1)
millis = int(round(time.time() * 5000))
interval = 2000
#print(millis)
if(int(millis-previous_millis) >= interval):
previous_millis = millis
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
#time.sleep(2)
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
cv2.putText(img, 'person', (x,y-10), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (255,0,0), 2)
cv2.imwrite('crop_faces/crop'+str(num)+'.jpg',roi_color)
num = num + 1
print ("FOUND", len(faces), 'PERSON')
total += len(faces)
print ('Total Count:', (total))
font = cv2.FONT_HERSHEY_SIMPLEX
img = cv2.circle(img, (470, 63), 63, (255,0,0), 3)
cv2.putText(img, 'Total Count:', (420,40), font, 0.5,(255,0,0),1,cv2.LINE_AA)
cv2.putText(img, str(total), (436,100), font, 2,(255,0,0),2,cv2.LINE_AA)
cv2.imshow('image',img)
k = cv2.waitKey(1) & 0xff
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
Make an empty list of faces. faces = []
Make a copy of the cropped face. face = numpy.copy(img[y:y+h,x:x+w])
Resize face to a fixed thumbnail size. Lets call the fixed size face_width, face_height.
Append face in the faces list. faces.append(face). Make sure the cropped face does not already exist in the list.
Select a point on the image, i.e px=0, py=0. Copy all the faces from the list to the image starting from px,py. img[py:py+face_height,px:px+face_width] = faces[0] ...
Related
Hey, I want to share a global NumpyArray(cameraImg) between my main
programm and the process which runs parallel. But it doesn't work. It says
"TypeError: only size-1 arrays can be converted to Python scalars"
The main Programm displa_camera() runs in a While Loop, and gets the Image of the Webcam. The img is saved in global cameraImg and used in recognize_faces() to identifiy the face depcit in the Image. It saves the name, which is added to the Image, above the Persons head. Hope you can help me, thx
import time, os, cv2 as cv2, face_recognition
from multiprocessing import Process, Array, Value
global name
name=""
window_name = 'facerecognition'
def display_camera():
cap = cv2.VideoCapture(0)
cap.set(3, 640) # set Width
cap.set(4, 480) # set Height
cascade = cv2.CascadeClassifier('cascade.xml')
global cameraImg, name
while True:
ret, img = cap.read()
cameraImg=Array('d',img)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = cascade.detectMultiScale(
gray,
scaleFactor=1.2,
minNeighbors=5,
minSize=(20, 20)
)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (36, 255, 12), 1)
cv2.putText(img, name, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36, 255, 12), 2)
roi_gray = gray[y:y + h, x:x + w]
roi_color = img[y:y + h, x:x + w]
cv2.imshow('video', img)
k = cv2.waitKey(30) & 0xff
if k == 27: # press 'ESC' to quit
break
cap.release()
cv2.destroyAllWindows()
def recognize_Faces():
global cameraImg, name
folder_dir = "../images/"
image_List=[]
for images in os.listdir(folder_dir):
# check if the image ends with png or jpg or jpeg
if (images.endswith(".png") or images.endswith(".jpg") \
or images.endswith(".jpeg")):
# display
image_List.append(images)
while True:
try:
newFaces=False
for path in image_List :
rgb_img = cv2.cvtColor(cameraImg, cv2.COLOR_BGR2RGB)
img_encoding = face_recognition.face_encodings(rgb_img)
img2 = cv2.imread("../images/"+path)
rgb_img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)
img_encoding2 = face_recognition.face_encodings(rgb_img2)[0]
result = face_recognition.compare_faces(img_encoding, img_encoding2)
print("Result: ", result)
if(result[0]):
newFaces=True
name= os.path.basename("../images/"+path).split('.')[0]
except Exception as e:
print(e)
if(newFaces==False):
name=""
k = cv2.waitKey(30) & 0xff
if k == 27: # press 'ESC' to quit
break
time.sleep(3)
if __name__ == '__main__':
secondaryThread = Process(target=recognize_Faces)
secondaryThread.start()
display_camera()
So I am trying to make a code where when face is detected from webcam it shows a green square around face. That part is done. What I want to make next is that when face is no longer detected by program that it break the loop and exit program. I tried ways through "if" or "else" or find something online but I was not going anywhere. Is there some way to do it? Here is my code:
import cv2
import os
import time
cascPath = os.path.dirname(
cv2.__file__) + "/data/haarcascade_frontalface_alt2.xml"
faceCascade = cv2.CascadeClassifier(cascPath)
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=(60, 60),
flags=cv2.CASCADE_SCALE_IMAGE)
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
video_capture.release()
cv2.destroyAllWindows()
How about adding this? Count the number of times no face is detected; break if passes a threshold:
iter_with_no_faces=0 #put this outside the main loop
### put the follwing after updating `faces`
if len(faces) ==0:
iter_with_no_faces+=1
## add break condition as this:
if iter_with_no_faces >100:
break
you can iter_with_no_faces in the faces loop: iter_with_no_faces=0
In sum, this might work with slight modification:
import cv2
import os
import time
cascPath = os.path.dirname(
cv2.__file__) + "/data/haarcascade_frontalface_alt2.xml"
faceCascade = cv2.CascadeClassifier(cascPath)
video_capture = cv2.VideoCapture(0)
iter_with_no_faces=0 #put this outside the main loop
while True:
ret, frame = video_capture.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(60, 60),
flags=cv2.CASCADE_SCALE_IMAGE)
for (x,y,w,h) in faces:
cv2.rectangle(frame, (x, y), (x + w, y + h),(0,255,0), 2)
if len(faces) ==0:
iter_with_no_faces+=1
else:
iter_with_no_faces=0 # I assume you want to continue program when a face detected for a duration. you can omit else statement
if iter_with_no_faces >100: #set this threshold to larger or smaller number
break
cv2.imshow('Video', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
video_capture.release()
cv2.destroyAllWindows()
import cv2
def main():
cascPath = './haarcascade_frontalface_alt2.xml' # path to the xml file - change to your path
faceCascade = cv2.CascadeClassifier(cascPath)
video_capture = cv2.VideoCapture(0)
for i in range(10 ** 10):
ret, frame = video_capture.read()
if ret:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(60, 60),
flags=cv2.CASCADE_SCALE_IMAGE)
if len(faces) > 0:
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow('Video', frame)
k = cv2.waitKey(1)
if k == ord('q'):
break
else:
print('No face detected on iter {}'.format(i))
# add here break or whatever you want to do if no face detected
video_capture.release()
cv2.destroyAllWindows()
return
if __name__ == '__main__':
main()
I tried to use Haar cascades called haarcascade_profileface.xml and lbpcascade_profileface.xml together but the camera does not even open at all. How can I fix this issue where I want both haar cascades to work?
This is done on the raspberry pi and can also run on Linux and windows as well. Please explain as best as possible! Here is the code:
import numpy as np
import cv2
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(18,GPIO.OUT)
face_cascade = cv2.CascadeClassifier('Haarcascade_profileface.xml')
side_face_cascade = cv2.CascadeClassifier('lbpcascade_frontalface_improved.xml')
prevTime = 0
## This will get our web camera
cap = cv2.VideoCapture(0)
font = cv2.FONT_HERSHEY_SIMPLEX
while True:
retval, frame = cap.read()
if not retval:
break
_, img = cap.read() ## This gets each frame from the video, cap.read returns 2 variables flag - indicate frame is correct and 2nd is f
##img = cv2.imread('Z.png') Then we get our image we want to use
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # This method only works on gray skin images, so we have to convert the gray scale to rgb image
faces = face_cascade.detectMultiScale(gray, 1.1, 5) ## Next, we detect the faces
if len(faces) > 0:
print("[INFO] found {0} faces!".format(len(faces)))
GPIO.output(18,GPIO.HIGH)
else:
print("No face")
GPIO.output(18,GPIO.LOW)
curTime = time.time()
sec = curTime - prevTime
prevTime = curTime
fps = 1/(sec)
str = "FPS : %0.1f" % fps
for (x, y, w, h) in faces: ## We draw a rectangle around the faces so we can see it correctly
cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0)) ## The faces will be a list of coordinates
cv2.putText(img, 'Myface', (x, y), font, fontScale=1, color=(255,70,120),thickness=2)
side_faces = side_face_cascade.detectMultiScale(gray, 1.1, 5)
for (ex, ey, ew, eh) in side_faces: ## We draw a rectangle around the faces so we can see it correctly
cv2.rectangle(img, (ex, ey), (ex+ew, ey+eh), (255, 0, 0)) ## The faces will be a list of coordinates
cv2.putText(img, 'Myface', (ex, ey), font, fontScale=1, color=(255,70,120),thickness=2)
cv2.putText(frame, 'Number of Faces Detected: ' + str, (0, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0))
cv2.imshow('img', img) ## Last we show the image
x = cv2.waitKey(30) & 0xff
if x==27:
break
## Press escape to exit the program
cap.release()
OpenCV actually provides a "side-face" detector. It is called 'haarcascade_profileface.xml'. You can do:
side_face_cascade = cv2.CascadeClassifier('haarcascade_profileface.xml')
side_faces = side_face_cascade.detectMultiScale(gray, 1.1, 5)
I'm looking to save/write photos that are not blurry. How would one go about combining the two codes below?
import cv2
image = cv2.imread('./facesData/ID.jpg')
cv2.Laplacian(image, cv2.CV_64F).var()
while 1:
ret, img = cap.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.2, 8)
for x,y,w,h in faces:
sampleN = sampleN + 1
cv2.imwrite("./facesData/ID." + str(sampleN) + ".jpg", gray[y:y+h, x:x+w])
cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0), 2)
cv2.waitKey(2)
cv2.imshow('user', img)
cv2.waitKey(1)
if sampleN > 20:
break
cap.release()
cv2.destroyAllWindows()
This moves your blurry images into a separate folder (code source).
# import the necessary packages
import cv2
import os
from pathlib import Path
#%% Setup paths
script_dir = str(Path(__file__).parents[0]) # path this script is running in
source_images_dir = os.path.join(script_dir, 'images')
#%%
def variance_of_laplacian(image):
# compute the Laplacian of the image and then return the focus
# measure, which is simply the variance of the Laplacian
return cv2.Laplacian(image, cv2.CV_64F).var()
#%% loop over the input images
threshold = 200
for file_name in os.listdir(source_images_dir):
image_path = os.path.join(source_images_dir, file_name)
image = cv2.imread(image_path) # load the image
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # convert to grayscale
fm = variance_of_laplacian(image) # calculate blur
text = "Not Blurry"
# if the focus measure is less than the supplied threshold,
# then the image should be considered "blurry"
if fm >= threshold:
text = "Blurry"
#%% Once ready to move clear images, uncomment this section
else:
focused_images_path = os.path.join(script_dir,
'blurry_images',
file_name)
os.rename(image_path, focused_images_path)
#%% Comment out the following section when ready to batch move your images
cv2.putText(image, "{}: {:.2f}".format(text, fm), (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3)
cv2.imshow("Image", image) # Press ENTER to cycle through images
key = cv2.waitKey(0)
To use it setup your folder structure like:
ret, frame = cap.read()
if face_extractor(frame) is not None:
count = count+1;
face = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY)
file_name_path = './facesData/ID.' +str(id)+ '.' +str(count)+ '.' + '.jpg'
if cv2.Laplacian(face, cv2.CV_64F).var() >500:
cv2.imwrite(file_name_path, face)
else:
count -= 1
cv2.imshow('user', frame)
else:
pass
if cv2.waitKey(1) == 13 or count == 20
I am having problems getting face detection and cropping an image to the face working, below is my code.
import cv2
class Crop:
#constructor
def __init__(self, image):
self.data = image
def facechop(self):
# read xml for training data
facedata = "haarcascade_frontalface_default.xml"
cascade = cv2.CascadeClassifier(facedata)
# read image file
img = cv2.imread(self.data, 0)
minisize = (img.shape[1], img.shape[0])
miniframe = cv2.resize(img, minisize)
faces = cascade.detectMultiScale(miniframe)
for f in faces:
x, y, w, h = [ v for v in f ]
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 255, 255))
sub_face = self.data[y:y + h, x:x + w]
# Show picture
cv2.imshow('img', sub_face)
return
input image file
picture = 'izz.jpg'
pic = Crop(gambar)
pic.facechop()
# keyboard input to destroy the window
while(True):
key = cv2.waitKey(0)
if key in [27, ord('Q'), ord('q')]:
break
when it's running, it doesn't do raw after for function till sub_face = self.data[y:y + h, x:x + w]. It directly goes to cv2.imshow('img', sub_face). So, sub_face is not known. Why does it not work well?
I'm using Aptana to debug it. Thank you.
Try changing your code to as follows:
import cv2
def crop(img):
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
sub_face = img
faces = face_cascade.detectMultiScale(img, 1.1, 5)
for (x,y,w,h) in faces:
sub_face = img[y:y+h, x:x+w]
return sub_face
imageToCrop = cv2.imread('izz.jpg',0)
croppedImage = crop(imageToCrop)
cv2.imshow('img',croppedImage)
cv2.waitKey(0)
cv2.destroyAllWindows()