I am using the below code for cropping faces from images in a directory
import cv2
import glob
import os
def facechop(image,imgname):
facedata = "haarcascade_frontalface_default.xml"
cascade = cv2.CascadeClassifier(facedata)
img = cv2.imread(image)
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 = img[y:y+h, x:x+w]
face_file_name = "faces/" + imgname + "_" + str(y) + ".jpg"
cv2.imwrite(face_file_name, sub_face)
# cv2.imshow(image, img)
# cv2.waitKey(0)
cv2.destroyAllWindows()
return
# if __name__ '__main__':
path = "images"
images = glob.glob(path + "/*")
for imgpath in images[0:]:
imagename = os.path.basename(imgpath)
imgname = os.path.splitext(imagename)[0]
facechop(imgpath, imgname)
print(imgname,"exported")
# while(True):
# key = cv2.waitKey(20)
# if key in [27, ord('Q'), ord('q')]:
# break
The code is too slow and sometimes even hangs the system. Please help improve.
1 Answer 1
So there are a couple of improvements that can be made to your code,
The first one would be, you are creating a new CascadeClassifier
object for every picture this is a costly operation.
The next is the fact that you are resizing the image, to the size of the image? I am unsure why you are doing that, depending on the size of the faces in your images you could resize them to be smaller and the search for faces in the picture.
Harr cascade detection is costly you can customize the parameters depending on the sizes of faces in your image.
Your code draws a box around every face and then isolates it, why is that? Lots of this code looks to be vestiges of old code. Removing old code can help make it more clear what is going on.
You number the face images based on the y value of the box; it would be much cleaner to simply report the index of the face (e.g. face 0, 1, 2, 3, etc...)
Based on this, here is some straightforward revised code that is much cleaner, but detectMultiScale
is still ~99% of the running time
import os
import cv2
image_path = "images"
def save_faces(cascade, imgname):
img = cv2.imread(os.path.join(image_path, imgname))
for i, face in enumerate(cascade.detectMultiScale(img)):
x, y, w, h = face
sub_face = img[y:y + h, x:x + w]
cv2.imwrite(os.path.join("faces", "{}_{}.jpg".format(imgname, i)), sub_face)
if __name__ == '__main__':
face_cascade = "haarcascade_frontalface_default.xml"
cascade = cv2.CascadeClassifier(face_cascade)
# Iterate through files
for f in [f for f in os.listdir(image_path) if os.path.isfile(os.path.join(image_path, f))]:
save_faces(cascade, f)
Explore related questions
See similar questions with these tags.
cv2.destroyAllWindows()
after commenting the 2 lines above? \$\endgroup\$