find_faces.pl
#!/usr/bin/perl
# Use OpenCV to detect faces in photos
# Most of this is take directly from a presentation at Ruhr.pm by Simon Wilper
# http://ruhr.pm.org/files/opencv/docshot/
use strict;
use warnings;
use 5.010;
use Image::ObjectDetect;
use Image::Magick;
use File::Next;
use File::Spec;
my $pic_src = '/mnt/pics/medium/2009';
my $face_dst = '/tmp/faces/';
my $cascade = '/usr/share/opencv/haarcascades/haarcascade_frontalface_alt.xml';
# haarcascade_frontalface_alt.xml haarcascade_fullbody.xml
# haarcascade_frontalface_alt2.xml haarcascade_lowerbody.xml
# haarcascade_frontalface_alt_tree.xml haarcascade_profileface.xml
# haarcascade_frontalface_default.xml haarcascade_upperbody.xml
mkdir $face_dst;
my $detector = Image::ObjectDetect->new($cascade);
my $files = File::Next::files( {
file_filter => sub { /\.jpg$/i }
},
$pic_src
);
while ( defined( my $file = $files->() ) ) {
my @faces = $detector->detect($file);
printf "%s -> %d\n", $file, scalar @faces;
next unless @faces;
( my $new_file = $file ) =~ s{(/mnt/pics/medium/|/)}{}g;
say "\t$new_file";
# This commented out section will save the found faces to individual
# files...
# my $i = 1;
# $im->Read($file);
# for my $face (@faces) {
# my $cropped_face = $im->Clone;
# $cropped_face->Crop(
# geometry => sprintf( "%dx%d+%d+%d",
# $face->{x}, $face->{y}, $face->{width}, $face->{height} ) );
# $cropped_face->Write( File::Spec->catfile( $face_dst, $i++ . ".jpg" ) );
# }
# Put a box around each detected face
my $im = Image::Magick->new;
$im->Read($file);
for my $face (@faces) {
$im->Draw(
primitive => 'rectangle',
points => sprintf( "%d,%d %d,%d",
$face->{x}, $face->{y},
$face->{x} + $face->{width}, $face->{y} + $face->{height} ),
stroke => 'red',
strokewidth => 2,
antialias => 1,
fill => 'rgba(100%,100%,0%,0.3)',
);
}
$im->Write( File::Spec->catfile( $face_dst, $new_file ) );
}