2017-10-12 2 views
1

Ich versuche ein Gesicht mit den Gesichtspunkten, die von dlib identifiziert wurden, zu beschneiden. Die rechte Augenbraue verursacht Probleme - die Ernte geht flach über den Augenbrauenbogen.Gesicht mit Dlib Facial Landmarks zuschneiden

Was mache ich hier falsch?

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

Ich bin nicht ganz sicher, Sie tun etwas falsch, ist es nicht nur angeblich diejenigen erkennen Punkte? [Quelle] (http://www.codesofinterest.com/2017/04/extracting-individual-facial-features-dlib.html) – GPPK

Antwort

0

Sein, weil die Gesichtsform Sie bereitstellen, sind nicht konvex ist. fillConvexPoly funktioniert nur bei konvexen Formen perfekt. In diesem Fall gibt es eine konkave Ecke (Punkt 27) und die Ergebnisse sind durcheinander.

Um dies zu beheben, ändern Sie die Funktion als

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

Diese würden Sie ein Ergebnis, das wie folgt aussieht. enter image description here

Jetzt können Sie etwas mehr Code schreiben, den dreieckigen Abschnitt auf der Stirn zu entfernen (wenn Sie es so wollen)

+0

Brilliant! Danke, das hat das Problem perfekt gelöst! Nun, da Sie es erwähnen, sieht auch Punkt # 16 - Punkt # 17 wie eine konkave Ecke aus und wurde von fillConvexPoly() gut toleriert. Irgendeine Idee warum das der Fall ist? – Squiggles

+0

Beim Anpassen der Punkte mit dlib würde es immer Fehler geben. Im Fall von Punkt 15-16-17 sind sie meistens in einer geraden Linie. Selbst ein kleinster Fehler könnte den Punkt 16 auf der linken Seite drücken und es zu einer konkaven Ecke machen. Dies zu beheben würde erfordern, dass Sie eine Teilmenge von Punkten in Form, aber nicht in cv2.convexHull (Form) finden. Und sie schleifen über diese Punkte, um den Rest des Gebiets abzudecken. –