Ask Your Question
0

OpenCV python: face crop program

asked 2016-03-12 14:03:18 -0600

green266 gravatar image

I was just experimenting with some code and I didn't do what I think it should of done (at least it worked).

So the code below was meant to identify faces saved in an "input" folder. Then it would detect all the faces sometimes the errors as well, and save them cropped in a separate "output" folder. Unfortunately It only saves the last face which was detected on the image rather than all the faces detected, including some of the errors. I tried to do a if eyes detected then statement to filter some errors out but it didn't work very well.

Will appreciate any help given

Thanks

Here is the code:

import numpy as np
import cv2
import os, os.path

#multiple cascades: https://github.com/Itseez/opencv/tree/master/data/haarcascades

#https://github.com/Itseez/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml
face_cascade = cv2.CascadeClassifier('faces.xml')
#https://github.com/Itseez/opencv/blob/master/data/haarcascades/haarcascade_eye.xml
eye_cascade = cv2.CascadeClassifier('eye.xml')

DIR = 'input'
numPics = len([name for name in os.listdir(DIR) if os.path.isfile(os.path.join(DIR, name))])

for pic in range(1, (numPics+1)):
    img = cv2.imread('input/'+str(pic)+'.jpg')
    height = img.shape[0]
    width = img.shape[1]
    size = height * width

    if size > (500^2):
        r = 500.0 / img.shape[1]
        dim = (500, int(img.shape[0] * r))
        img2 = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
        img = img2

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)
    eyesn = 0

    for (x,y,w,h) in faces:
        imgCrop = img[y:y+h,x:x+w]
        #cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
        roi_gray = gray[y:y+h, x:x+w]
        roi_color = img[y:y+h, x:x+w]

        eyes = eye_cascade.detectMultiScale(roi_gray)
        for (ex,ey,ew,eh) in eyes:
            #cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
            eyesn = eyesn +1
        if eyesn >= 2:
            cv2.imwrite("output/crop"+str(pic)+".jpg", imgCrop)

    #cv2.imshow('img',imgCrop)
    print("Image"+str(pic)+" has been processed and cropped")
    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break

#cap.release()
print("All images have been processed!!!")
cv2.destroyAllWindows()
cv2.destroyAllWindows()
edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
0

answered 2016-03-13 01:46:08 -0600

berak gravatar image

you just need another counter variable:

n = 0
for (x,y,w,h) in faces:
        ...
        cv2.imwrite("output/crop"+str(pic)+ "_" +str(n)+".jpg", imgCrop)
        n += 1
edit flag offensive delete link more

Comments

Thanks for the help

Works nearly perfectly now!! Just ran a 100 hundred images on it only made a few mistakes by detecting two faces in one. Surprisingly I think the program's a bit racist as it just doesn't work very well with coloured people. Apparently Obama has a two faces.

green266 gravatar imagegreen266 ( 2016-03-13 05:27:51 -0600 )edit

to reduce false positives, you can try to increase the 'minNeighbours' param in detectMultiScale()

berak gravatar imageberak ( 2016-03-13 05:33:17 -0600 )edit

Ye thanks I found that 500 x 500 worked best with 1.7 and 5

green266 gravatar imagegreen266 ( 2016-03-14 11:18:37 -0600 )edit

not able to detect eyes.. i actually tried with single image.. please help

sheikha gravatar imagesheikha ( 2017-02-26 10:54:15 -0600 )edit

@sheikha, please ask your own question !

berak gravatar imageberak ( 2017-02-26 11:16:11 -0600 )edit
0

answered 2016-03-18 21:14:20 -0600

Hello, I'm a first time poster. I am about to install python and opencv and try a variation of the above, eventually leading to video face tracking using Haar Cascade face detection (as above) with face tracking with Lucas-Kanade optical flow as per this https://www.youtube.com/watch?v=JO8XH... I'm unsure of the reason for the image resize in the code above, any hints ? Googling showed many variants on the above code, I hope this code includes a couple of minor changes which work:

#http://answers.opencv.org/question/90010/opencv-python-face-crop-program/
#
#to reduce false positives, you can try to increase the 'minNeighbours' param in detectMultiScale()
#Ye thanks I found that 500 x 500 worked best with 1.7 and 5
#
#https://realpython.com/blog/python/face-recognition-with-python/
#If you want to use OpenCV3 just change "cv2.cv.CV_HAAR_SCALE_IMAGE" to "cv2.CASCADE_SCALE_IMAGE", it works for me
#faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(20, 20), flags = cv2.CASCADE_SCALE_IMAGE )

import numpy as np
import cv2
import os, os.path

#multiple cascades: https://github.com/Itseez/opencv/tree/master/data/haarcascades
#https://github.com/Itseez/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml
face_cascade = cv2.CascadeClassifier('faces.xml')
#https://github.com/Itseez/opencv/blob/master/data/haarcascades/haarcascade_eye.xml
eye_cascade = cv2.CascadeClassifier('eye.xml')

DIR = 'input'
numPics = len([name for name in os.listdir(DIR) if os.path.isfile(os.path.join(DIR, name))])

nfaces_detected = 0
for pic in range(1, (numPics+1)):
# note the dependency on the format of the filename 
    img = cv2.imread('input/'+str(pic)+'.jpg')
    height = img.shape[0]
    width = img.shape[1]
    size = height * width
#???
#    if size > (500^2):
#        r = 500.0 / img.shape[1]
#        dim = (500, int(img.shape[0] * r))
#        img2 = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
#        img = img2

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    #faces = face_cascade.detectMultiScale(gray, 1.3, 5)
    faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(15, 15), flags = cv2.CASCADE_SCALE_IMAGE )

    nface_within_pic = 0
    for (x,y,w,h) in faces:
        face_with_eyes_detected = 0
        imgCrop = img[y:y+h,x:x+w]
        #cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
        roi_gray = gray[y:y+h, x:x+w]
        roi_color = img[y:y+h, x:x+w]

        #eyes = eye_cascade.detectMultiScale(roi_gray)
        eyes = faceCascade.detectMultiScale(roigray, scaleFactor=1.1, minNeighbors=5, minSize=(5, 5), flags = cv2.CASCADE_SCALE_IMAGE )
        eyesn = 0
        for (ex,ey,ew,eh) in eyes:
            #cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
            eyesn = eyesn +1
# allow detection if only one 1 eye for sideways face profile ?  
# No, always assume a frontal profile since that's the haar detection profile we chose above
#        if eyesn >= 1:
        if eyesn >= 2:
            face_with_eyes_detected = 1
        #cv2.imshow('img',imgCrop)
        if face_with_eyes_detected > 0:
            cv2.imwrite("output/crop"+str(pic)+ "_" +str(nface_within_pic)+".jpg", imgCrop)
            print("Image"+str(pic)+ "_" +str(nface_within_pic)+" has been processed and cropped")
            nface_within_pic += 1
            nfaces_detected += 1
    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break

print("All "+str ...
(more)
edit flag offensive delete link more

Comments

1
  • please, if you have a question, ask a question, don't make an answer. (for the future..)

  • imho, the reason for the resize() in the question code above might be to speed up the cascade detection

berak gravatar imageberak ( 2016-03-19 01:17:01 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2016-03-12 14:03:18 -0600

Seen: 5,537 times

Last updated: Mar 18 '16