简体   繁体   中英

Cropping faces from an image using OpenCV in Python

I'm currently trying to crop faces from an image.

I want the code to work no matter how many faces are in the image.

An example of the input image: Image with faces

I'd like to crop the faces so I can run a facial keypoint detection algorithm on them (previously made).

The end result will look something like this: Image after facial keypoint detection

My code is currently:

# Load in color image for face detection
image = cv2.imread('images/obamas4.jpg')

# Convert the image to RGB colorspace
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# Make a copy of the original image to draw face detections on
image_copy = np.copy(image)

# Convert the image to gray 
gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

# Detect faces in the image using pre-trained face dectector
faces = face_cascade.detectMultiScale(gray_image, 1.25, 6)

# Print number of faces found
print('Number of faces detected:', len(faces))

# Get the bounding box for each detected face
for f in faces:
    x, y, w, h = [ v for v in f ]
    cv2.rectangle(image_copy, (x,y), (x+w, y+h), (255,0,0), 3)
    # Define the region of interest in the image  
    face_crop = gray_image[y:y+h, x:x+w]

# Display the image with the bounding boxes
fig = plt.figure(figsize = (9,9))
axl = fig.add_subplot(111)
axl.set_xticks([])
axl.set_yticks([])

ax1.set_title("Obamas with Face Detection")
axl.imshow(image_copy)

# Display the face crops
fig = plt.figure(figsize = (9,9))
axl = fig.add_subplot(111)
axl.set_xticks([])
axl.set_yticks([])

axl.set_title("Obamas Face Crops")
axl.imshow(face_crop)

The output looks like this: enter image description here

Right now it only outputs the last face detected in the image. I'm certain I'm missing something simple like a for loop.

I'd like to be able to run my facial keypoint detection algorithm on all of the gray cropped face images.

Thank you for your help!

The problem is in your code, face_crop is storing only the last face detected.

So make it as a list and append all faces to it. Then use a for loop to display all faces. Like this:

face_crop = []
for f in faces:
    x, y, w, h = [ v for v in f ]
    cv2.rectangle(image_copy, (x,y), (x+w, y+h), (255,0,0), 3)
    # Define the region of interest in the image  
    face_crop.append(gray_image[y:y+h, x:x+w])

for face in face_crop:
    cv2.imshow('face',face)
    cv2.waitKey(0)

I used cv2.imshow() to display the images. You can modify this to use plt.imshow()

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM