Search code examples
pythonopencvface-detection

OpenCV detect face landmarks (ear-chin-ear line)


I am looking to an opencv function (in python) detecting the line left ear - chin - right ear (that looks like a parabol) on human faces. Is there any kind of haarcascade doing this job? I already know the frontal face or the eyes haarcascades but I am looking for something more precise.


Solution

  • what you are looking for is called face landmark detection . You can try DLIB . DLIB is written in C++ but it also have a python wrapper .Install Instructions

    Now using DLib you can achieve this

    Code

    import cv2
    import dlib
    import numpy
    
    PREDICTOR_PATH = "/home/zed/dlib/files/shape_predictor_68_face_landmarks.dat"
    predictor = dlib.shape_predictor(PREDICTOR_PATH)
    cascade_path='haarcascade_frontalface_default.xml'
    cascade = cv2.CascadeClassifier(cascade_path)
    
    # #This is using the Dlib Face Detector . Better result more time taking
    # def get_landmarks(im):
    #     rects = detector(im, 1)
    #     rect=rects[0]
    #     print type(rect.width())
    #     fwd=int(rect.width())
    #     if len(rects) == 0:
    #         return None,None
    
    #     return np.matrix([[p.x, p.y] for p in predictor(im, rects[0]).parts()]),fwd
    
    def get_landmarks(im):
        rects = cascade.detectMultiScale(im, 1.3,5)
        x,y,w,h =rects[0]
        rect=dlib.rectangle(x,y,x+w,y+h)
        return numpy.matrix([[p.x, p.y] for p in predictor(im, rect).parts()])
    
    def annotate_landmarks(im, landmarks):
        im = im.copy()
        for idx, point in enumerate(landmarks):
            pos = (point[0, 0], point[0, 1])
            cv2.putText(im, str(idx), pos,
                        fontFace=cv2.FONT_HERSHEY_SCRIPT_SIMPLEX,
                        fontScale=0.4,
                        color=(0, 0, 255))
            cv2.circle(im, pos, 3, color=(0, 255, 255))
        return im
    
    im=cv2.imread('face_leo1.jpg')
    cv2.imshow('Result',annotate_landmarks(im,get_landmarks(im)))
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    Results

    enter image description here

    Points related to landmark :

    FACE_POINTS = list(range(17, 68))
    MOUTH_POINTS = list(range(48, 61))
    RIGHT_BROW_POINTS = list(range(17, 22))
    LEFT_BROW_POINTS = list(range(22, 27))
    RIGHT_EYE_POINTS = list(range(36, 42))
    LEFT_EYE_POINTS = list(range(42, 48))
    NOSE_POINTS = list(range(27, 35))
    JAW_POINTS = list(range(0, 17))
    CHIN_POINTS=list(range(6,11))