Search code examples
pythonopencvface-detection

Cv2 all Facial features detection


I have a program that detects the eyes, mouth, nose and face but it is very inaccurate. This is my code:

import numpy as np
import cv2
face_cascade = cv2.CascadeClassifier('face.xml')
mouth_cascade = cv2.CascadeClassifier('mouth.xml')
nose_cascade = cv2.CascadeClassifier('nose.xml')
eye_cascade = cv2.CascadeClassifier('eye.xml')


image = cv2.imread("img.jpg")
grayImage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

face = face_cascade.detectMultiScale(grayImage, minNeighbors=5)
mouth = mouth_cascade.detectMultiScale(grayImage, minNeighbors=5)
nose = nose_cascade.detectMultiScale(grayImage, minNeighbors=5)
eye = eye_cascade.detectMultiScale(grayImage, minNeighbors=5)

print(type(face))

if len(face) == 0:
    print("No faces found")

else:
    print("mouth")
    print(mouth)
    print(mouth.shape)
    print("Number of mouths detected: " + str(mouth.shape[0]))

    print("Face")
    print(face)
    print(face.shape)
    print("Number of faces detected: " + str(face.shape[0]))

    print("nose")
    print(nose)
    print(nose.shape)
    print("Number of noses detected: " + str(nose.shape[0]))

    print("eye")
    print(eye)
    print(eye.shape)
    print("Number of eye detected: " + str(eye.shape[0]))

    for (x,y,w,h) in face:
        cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),1)

    for (x,y,w,h) in mouth:
        cv2.rectangle(image,(x,y),(x+w,y+h),(255,0,0),1)

    for (x,y,w,h) in nose:
        cv2.rectangle(image,(x,y),(x+w,y+h),(255,255,255),1)

    for (x,y,w,h) in eye:
        cv2.rectangle(image,(x,y),(x+w,y+h),(255,255,0),1)


cv2.imshow('Image with faces',image)
cv2.waitKey(0)
cv2.destroyAllWindows()

I expect it to look like this.

The actual result is this.

I also would like it to show the ears and hair.
Also can this be preferably without dlib as I am unable to use it. Thanks in advance.


Solution

  • Use below code as starting point. You will have to tune parameters to get better results.

    image = cv2.imread("sample_face.jpeg")
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    face = face_cascade.detectMultiScale(gray, minNeighbors=5)
    
    if len(face) == 0:
        print("No faces found")
    
    else:
    
        for (x,y,w,h) in face:
            cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)
            roi_gray = gray[y:y+h, x:x+w]
            roi_color = image[y:y+h, x:x+w]
    
            eye = eye_cascade.detectMultiScale(roi_gray, 
                                               minSize=(80, 30),
                                               minNeighbors=5)
            for (ex,ey,ew,eh) in eye:
                cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(255,255,0),2)
    
    
            nose = nose_cascade.detectMultiScale(roi_gray, 
                                                 scaleFactor=4.9, 
                                                 minNeighbors=4, 
                                                 flags=cv2.CASCADE_SCALE_IMAGE)
    
            for (nx,ny,nw,nh) in nose:
                cv2.rectangle(roi_color,(nx,ny),(nx+nw,ny+nh),(255,255,255),2)
    
            mouth = mouth_cascade.detectMultiScale(roi_gray, 
                                                   scaleFactor=1.1, 
                                                   maxSize=(100,150))
            for (mx,my,mw,mh) in mouth:
                cv2.rectangle(roi_color,(mx,my),(mx+mw,my+mh),(255,0,0),2)
    

    Also, go through this tutorial on how to do face detection using Haar Feature-based Cascade Classifiers.