Cropping faces from images in a directory 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.
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)