Skip to content

Instantly share code, notes, and snippets.

@jo32
Created May 13, 2013 12:41
Show Gist options
  • Save jo32/5568048 to your computer and use it in GitHub Desktop.
Save jo32/5568048 to your computer and use it in GitHub Desktop.
face detection using OpeCV haar detection and save them
#!/usr/bin/python
"""
This program is used for face detection and save the faces it detects.
"""
import sys
import re
import cv2
import cv2.cv as cv
import numpy
from optparse import OptionParser
from datetime import datetime
"""
Parameters for haar detection:
min_size: minimum face size is 20 * 20.
image_scale: scale factor is 1.2
haar_scale: haar scale is 1.2
haar_flags: Mode of operation. Currently the only flag that may be specified is
CV_HAAR_DO_CANNY_PRUNING.
"""
min_size = (20, 20)
image_scale = 2
haar_scale = 1.2
min_neighbors = 2
haar_flags = 0
# get the filename to save
def get_file_name(index):
time = str(datetime.now())
time = re.sub(r"\D", "", time)
prefix = "faces/" + time
return prefix + "_" + str(index) + ".jpg"
class FaceDetector(object):
def __init__(self):
super(FaceDetector, self).__init__()
# initially setting the number of face as 0
self.no_faces = 0
def save_faces(self, image, faces):
# if there is new faces enter the screen, save them.
if len(faces) <= self.no_faces:
if len(faces) != self.no_faces:
self.no_faces = len(faces)
return
index = 0
print "Saving %d faces ..." % self.no_faces
for ((x, y, w, h), n) in faces:
# rescaling x, y, w, h parameters to the original size
x *= image_scale
y *= image_scale
w *= image_scale
h *= image_scale
# getting the detected sub region of the face
src_region = cv.GetSubRect(image, (x, y, w, h))
# crop the image
cropped = cv.CreateImage((w, h), image.depth, image.nChannels)
cv.Copy(src_region, cropped)
# save the image to the 'filename'
filename = get_file_name(index)
array = numpy.asarray(cropped[:, :])
cv2.imwrite(filename, array)
index += 1
self.no_faces = len(faces)
# the function used to detect and draw the result of a image
def detect_and_draw(self, img, cascade):
# allocate temporary images
# create a image with depth level is 8 and 1 channels.
gray = cv.CreateImage((img.width, img.height), 8, 1)
# the size of small image
size = (cv.Round(img.width / image_scale),
cv.Round(img.height / image_scale))
# create a small image
small_img = cv.CreateImage(size, 8, 1)
# convert color input image to grayscale
cv.CvtColor(img, gray, cv.CV_BGR2GRAY)
# scale input image for faster processing
cv.Resize(gray, small_img, cv.CV_INTER_LINEAR)
# Histogram Equalization
cv.EqualizeHist(small_img, small_img)
# using the cascade input to do haar detection
if(cascade):
# getting the tick count
t = cv.GetTickCount()
# doing the haar detection using API HaarDetectObjects
faces = cv.HaarDetectObjects(
small_img,
cascade,
cv.CreateMemStorage(0),
haar_scale,
min_neighbors,
haar_flags,
min_size
)
# get and print the time spent to do the haar face detection
t = cv.GetTickCount() - t
print "detection time = %gms" % \
(t / (cv.GetTickFrequency() * 1000.))
if faces:
self.save_faces(img, faces)
# drawing each object detected with a rectangle
for ((x, y, w, h), n) in faces:
# the input to cv.HaarDetectObjects was resized, so scale
# the bounding box of each face and convert it to
# two CvPoints
pt1 = (
int(x * image_scale),
int(y * image_scale)
)
pt2 = (
int((x + w) * image_scale),
int((y + h) * image_scale)
)
cv.Rectangle(img, pt1, pt2, cv.RGB(0, 119, 34), 3, 8, 0)
else:
self.no_faces = 0
cv.ShowImage("result", img)
if __name__ == '__main__':
# adding the cascade file option
parser = OptionParser(
usage="usage: %prog [options] [filename|camera_index]")
parser.add_option(
"-c", "--cascade", action="store", dest="cascade", type="str",
help="Haar cascade file, default %default",
default="face.xml")
(options, args) = parser.parse_args()
cascade = cv.Load(options.cascade)
if len(args) != 1:
parser.print_help()
sys.exit(1)
input_name = args[0]
if input_name.isdigit():
capture = cv.CreateCameraCapture(int(input_name))
else:
capture = None
cv.NamedWindow("result", 1)
width = 320 # leave None for auto-detection
height = 240 # leave None for auto-detection
if width is None:
width = int(cv.GetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH))
else:
cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH, width)
if height is None:
height = int(cv.GetCaptureProperty(
capture, cv.CV_CAP_PROP_FRAME_HEIGHT))
else:
cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT, height)
face_detector = FaceDetector()
if capture:
frame_copy = None
while True:
frame = cv.QueryFrame(capture)
if not frame:
cv.WaitKey(0)
break
if not frame_copy:
frame_copy = cv.CreateImage((frame.width, frame.height),
cv.IPL_DEPTH_8U, frame.nChannels)
if frame.origin == cv.IPL_ORIGIN_TL:
cv.Copy(frame, frame_copy)
else:
cv.Flip(frame, frame_copy, 0)
face_detector.detect_and_draw(frame_copy, cascade)
if cv.WaitKey(10) >= 0:
break
else:
image = cv.LoadImage(input_name, 1)
face_detector.detect_and_draw(image, cascade)
cv.WaitKey(0)
cv.DestroyWindow("result")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment