2017-10-12 8 views
1

J'essaie de recadrer un visage en utilisant les repères faciaux identifiés par dlib. Le sourcil droit cause des problèmes - la culture va à plat plutôt que de suivre l'arc des sourcils.Recadrage du visage à l'aide des repères faciaux dlib

Qu'est-ce que je fais mal ici?

from imutils import face_utils 
import imutils 
import numpy as np 
import collections 
import dlib 
import cv2 

def face_remap(shape): 
    remapped_image = shape.copy() 
    # left eye brow 
    remapped_image[17] = shape[26] 
    remapped_image[18] = shape[25] 
    remapped_image[19] = shape[24] 
    remapped_image[20] = shape[23] 
    remapped_image[21] = shape[22] 
    # right eye brow 
    remapped_image[22] = shape[21] 
    remapped_image[23] = shape[20] 
    remapped_image[24] = shape[19] 
    remapped_image[25] = shape[18] 
    remapped_image[26] = shape[17] 
    # neatening 
    remapped_image[27] = shape[0] 

    return remapped_image 

""" 
MAIN CODE STARTS HERE 
""" 
# load the input image, resize it, and convert it to grayscale 
image = cv2.imread("images/faceCM1.jpg") 
image = imutils.resize(image, width=500) 
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 

out_face = np.zeros_like(image) 

# initialize dlib's face detector (HOG-based) and then create the facial landmark predictor 
detector = dlib.get_frontal_face_detector() 
predictor = dlib.shape_predictor(SHAPE_PREDICTOR) 

# detect faces in the grayscale image 
rects = detector(gray, 1) 

# loop over the face detections 
for (i, rect) in enumerate(rects): 
    """ 
    Determine the facial landmarks for the face region, then convert the facial landmark (x, y)-coordinates to a NumPy array 
    """ 
    shape = predictor(gray, rect) 
    shape = face_utils.shape_to_np(shape) 

    #initialize mask array 
    remapped_shape = np.zeros_like(shape) 
    feature_mask = np.zeros((image.shape[0], image.shape[1])) 

    # we extract the face 
    remapped_shape = face_remap(shape) 
    cv2.fillConvexPoly(feature_mask, remapped_shape[0:27], 1) 
    feature_mask = feature_mask.astype(np.bool) 
    out_face[feature_mask] = image[feature_mask] 
    cv2.imshow("mask_inv", out_face) 
    cv2.imwrite("out_face.png", out_face) 

sample image of cropped face showing the issue

+0

Im pas tout à fait sûr que vous faites quelque chose de mal, ne l'est pas seulement censé détecter les points? [source] (http://www.codesofinterest.com/2017/04/extracting-individual-facial-features-dlib.html) – GPPK

Répondre

0

Son parce que la forme du visage que vous fournissez n'est pas convexe. fillConvexPoly fonctionne parfaitement sur des formes convexes uniquement. Dans ce cas, il y a un coin concave (au point n ° 27) et les résultats sont donc erronés.

Pour résoudre ce problème, modifiez la fonction

def face_remap(shape): 
    remapped_image = cv2.convexHull(shape) 
    return remapped_image 

Cela vous donne un résultat qui ressemble. enter image description here

Maintenant, vous pouvez écrire un peu plus de code pour supprimer la section triangulaire sur le front (si vous le voulez de cette façon)

+0

Brillant! Merci, cela a résolu le problème parfaitement! Maintenant que vous le mentionnez, pt # 16 - pt # 17 ressemble à un coin concave et a été bien toléré par fillConvexPoly(). Une idée de pourquoi c'est le cas? – Squiggles

+0

Il y aura toujours des erreurs lors de l'ajustement des points en utilisant dlib. Dans le cas du point # 15-16-17, ils sont pour la plupart en ligne droite. Même la moindre erreur pourrait pousser le point # 16 sur la gauche en faisant un coin concave. En corrigeant ceci, vous devrez trouver un sous-ensemble de points en forme mais pas en cv2.convexHull (forme). Et ils bouclent ces points pour couvrir le reste de la zone. –