0

Is there any way i can make my own train set for face recognition in python ? To be more specific i want to make a train set like an AT&T Face database. I want my camera to take 20 images of each person(30 max) and store it in the separate folders by the name of each person.

import cv2, sys, numpy, os
size = 4
fn_haar = 'haarcascade_frontalface_default.xml'
fn_dir = 'att_faces'
fn_name = sys.argv[1]
path = os.path.join(fn_dir, fn_name)
if not os.path.isdir(path):
    os.mkdir(path)
(im_width, im_height) = (112, 92)
haar_cascade = cv2.CascadeClassifier(fn_haar)
webcam = cv2.VideoCapture(0)

# The program loops until it has 20 images of the face.
count = 0
while count < 20:
    (rval, im) = webcam.read()
    im = cv2.flip(im, 1, 0)
    gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    mini = cv2.resize(gray, (gray.shape[1] / size, gray.shape[0] / size))
    faces = haar_cascade.detectMultiScale(mini)
    faces = sorted(faces, key=lambda x: x[3])
    if faces:
        face_i = faces[0]
        (x, y, w, h) = [v * size for v in face_i]
        face = gray[y:y + h, x:x + w]
        face_resize = cv2.resize(face, (im_width, im_height))
        pin=sorted([int(n[:n.find('.')]) for n in os.listdir(path)
               if n[0]!='.' ]+[0])[-1] + 1
        cv2.imwrite('%s/%s.png' % (path, pin), face_resize)
        cv2.rectangle(im, (x, y), (x + w, y + h), (0, 255, 0), 3)
        cv2.putText(im, fn_name, (x - 10, y - 10), cv2.FONT_HERSHEY_PLAIN,
            1,(0, 255, 0))
        count += 1
    cv2.imshow('OpenCV', im)
    key = cv2.waitKey(10)
    if key == 27:
        break
Irum Zahra Awan
  • 276
  • 1
  • 5
  • 16
  • I'm confused as to what you're trying to do. Do you want opencv to take 30 pictures of a person for you? Or do you have the pictures and do you want to train a detector? – user3543300 Sep 26 '16 at 07:13
  • Can you be more specific where are you facing problems ? Share the piece of code you have written so far ? – ZdaR Sep 26 '16 at 07:53
  • this code is taking 20 pictures of a face detected and saves it in a folder than terminates. I want to edit it. it should take 20 pictures of each face which is detected and saves each face in separate folder. it should not terminate on its own. – Irum Zahra Awan Sep 27 '16 at 05:49
  • code is added.. – Irum Zahra Awan Sep 27 '16 at 05:55
  • @user3543300 this code is taking 20 pictures of a face detected and saves it in a folder than terminates. I want to edit it. it should take 20 pictures of each face which is detected and saves each face in separate folder. it should not terminate on its own – Irum Zahra Awan Oct 03 '16 at 07:27
  • @ZdaR this code is taking 20 pictures of a face detected and saves it in a folder than terminates. I want to edit it. it should take 20 pictures of each face which is detected and saves each face in separate folder. it should not terminate on its own – Irum Zahra Awan Oct 03 '16 at 07:28

1 Answers1

1

For this, you just need to provide a particular path to save all the image with (.png) or (.bmp) or (.jpg) extension in a sorted manner.

# train.py
import cv2, sys, numpy, os
size = 4
fn_haar = 'haarcascade_frontalface_default.xml'
fn_dir = 'face_data'

fn_name = sys.argv[0]


path = os.path.join(fn_dir, fn_name)

(im_width, im_height) = (112, 92)
haar_cascade = cv2.CascadeClassifier(fn_haar)
webcam = cv2.VideoCapture(0)

# Generate name for image file
pin=sorted([int(n[:n.find('.')]) for n in os.listdir(path)
 if n[0]!='.' ]+[0])[-1] + 1

# Beginning message
print("\n\033[94mThe program will save 20 samples. \
Move your head around to increase while it runs.\033[0m\n")

# The program loops until it has 20 images of the face.
count = 0
pause = 0
count_max = 20
while count < count_max:

  # Loop until the camera is working
  rval = False
  while(not rval):
    # Put the image from the webcam into 'frame'
    (rval, frame) = webcam.read()
    if(not rval):
        print("Failed to open webcam. Trying again...")

# Get image size
height, width, channels = frame.shape

# Flip frame
frame = cv2.flip(frame, 1, 0)

# Convert to grayscale
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# Scale down for speed
mini = cv2.resize(gray, (int(gray.shape[1] / size), int(gray.shape[0] / size)))

# Detect faces
faces = haar_cascade.detectMultiScale(mini)

# We only consider largest face
faces = sorted(faces, key=lambda x: x[3])
if faces:
    face_i = faces[0]
    (x, y, w, h) = [v * size for v in face_i]

    face = gray[y:y + h, x:x + w]
    face_resize = cv2.resize(face, (im_width, im_height))

    # Draw rectangle and write name
    cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)
    cv2.putText(frame, fn_name, (x - 10, y - 10), cv2.FONT_HERSHEY_PLAIN,
        1,(0, 255, 0))

    # Remove false positives
    if(w * 6 < width or h * 6 < height):
        print("Face too small")
    else:

        # To create diversity, only save every fith detected image
        if(pause == 0):

            print("Saving training sample "+str(count+1)+"/"+str(count_max))

            # Save image file
            cv2.imwrite('%s/%s.png' % (path, pin), face_resize)

            pin += 1
            count += 1

            pause = 1

if(pause > 0):
    pause = (pause + 1) % 5
cv2.imshow('OpenCV', frame)
key = cv2.waitKey(10)
if key == 27:
    break

This code will help you to get the cropped images from the webcam and store them in a directory name as face_data for training purpose. In case, you don't want to train your dataset from webcam, you can simply do one thing: that just create a directory and create 5-6 sub-directory in it as in Happy, Sad, Angry, Neutral, Calm, etc. Download the images and put them in corresponding folders for training purpose, now follow this code.

## This program first ensures if the face of a person exists in the given image or 
not then if it exists, it crops
## the image of the face and saves to the given directory.

## Importing Modules
import cv2
import os


directory = "C:\\Users\\hp"

## directory where the images to be saved:
f_directory = "C:\\Users\\hp\\face_data/"

def facecrop(image):
   ## Crops the face of a person from an image!

   ## OpenCV XML FILE for Frontal Facial Detection using HAAR CASCADES.
   facedata=    
   "C:\\opencv\\build\\etc\\haarcascades\\haarcascade_frontalface_default.xml"
   cascade = cv2.CascadeClassifier(facedata)

   ## Reading the given Image with OpenCV
   img = cv2.imread(image)

   try:    
    minisize = (img.shape[1],img.shape[0])
    miniframe = cv2.resize(img, minisize)

    faces = cascade.detectMultiScale(miniframe)

    for f in faces:
        x, y, w, h = [ v for v in f ]
        cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)

        sub_face = img[y:y+h, x:x+w]

        f_name = image.split('/')
        f_name = f_name[-1]

        ## Change here the Desired directory.
        cv2.imwrite(f_directory + f_name, sub_face)
        print ("Writing: " + image)

except:
    pass

if __name__ == '__main__':
    images = os.listdir(directory)
    i = 0

for img in images:
    file = directory + img
    print (i)
    facecrop(file)
    i += 1
  • I am confused what is the purpose of using v * size in the loop? where size=2 or 4 face_i = faces[0] (x, y, w, h) = [v * size for v in face_i] – Mansi mishra Jun 12 '23 at 10:30