Share/Bookmark

Featured Posts

Video Game Website Gives all it's profit to Charity Sometimes you read an article that just makes you smile, this is such one: http://www.ps3attitude.com/new/2010/02/no-fuss-reviews-4000-charity/ A video game review website that has given all of it's...

Read more

SQL AD Group membership Hi all, I have been working on a way to return Active directory group membership from a linked AD server in SQL. Its quite hard as you can`t return it from the group - you have to return it from...

Read more

Face Detection with PHP A very useful piece of PHP code that will highlight any pictures where a face has been detected. Heres the first piece of PHP code you will need, it would be best to make this an include: [sourcecode...

Read more

Basic Guide to Database Normalisation: First Normal... Before I start talking about the normal forms, I thought it would be best to explain what I am planning to write about, and what normalisation is. I am going to cover what normalisation is for beginners...

Read more

Sony: Synonymous with Innovation Sony have always been on the leading edge of innovation. From creating the WalkMan back in the 80's to popularising the CD, DVD and Blu-Ray with their PlayStation products. In this article we're discussing...

Read more

Face Detection with PHP

Posted by matthew | Posted in Code Snippets | Posted on 30-12-2009

Tags: ,

1

A very useful piece of PHP code that will highlight any pictures where a face has been detected.

Heres the first piece of PHP code you will need, it would be best to make this an include:


class Face_Detector {

protected $detection_data;
protected $canvas;
protected $face;
private $reduced_canvas;

public function __construct($detection_file = 'detection.dat') {
if (is_file($detection_file)) {
$this->detection_data = unserialize(file_get_contents($detection_file));
} else {
throw new Exception("Couldn't load detection data");
}
//$this->detection_data = json_decode(file_get_contents('data.js'));
}

public function face_detect($file) {
if (!is_file($file)) {
throw new Exception("Can not load $file");
}

$this->canvas = imagecreatefromjpeg($file);
$im_width = imagesx($this->canvas);
$im_height = imagesy($this->canvas);

//Resample before detection?
$ratio = 0;
$diff_width = 320 - $im_width;
$diff_height = 240 - $im_height;
if ($diff_width > $diff_height) {
$ratio = $im_width / 320;
} else {
$ratio = $im_height / 240;
}

if ($ratio != 0) {
$this->reduced_canvas = imagecreatetruecolor($im_width / $ratio, $im_height / $ratio);
imagecopyresampled($this->reduced_canvas, $this->canvas, 0, 0, 0, 0, $im_width / $ratio, $im_height / $ratio, $im_width, $im_height);

$stats = $this->get_img_stats($this->reduced_canvas);
$this->face = $this->do_detect_greedy_big_to_small($stats['ii'], $stats['ii2'], $stats['width'], $stats['height']);
$this->face['x'] *= $ratio;
$this->face['y'] *= $ratio;
$this->face['w'] *= $ratio;
} else {
$stats = $this->get_img_stats($this->canvas);
$this->face = $this->do_detect_greedy_big_to_small($stats['ii'], $stats['ii2'], $stats['width'], $stats['height']);
}
return ($this->face['w'] > 0);
}

public function toJpeg() {
$color = imagecolorallocate($this->canvas, 255, 0, 0); //red
imagerectangle($this->canvas, $this->face['x'], $this->face['y'], $this->face['x']+$this->face['w'], $this->face['y']+ $this->face['w'], $color);
header('Content-type: image/jpeg');
imagejpeg($this->canvas);
}

public function toJson() {
return "{'x':" . $this->face['x'] . ", 'y':" . $this->face['y'] . ", 'w':" . $this->face['w'] . "}";
}

public function getFace() {
return $this->face;
}

protected function get_img_stats($canvas){
$image_width = imagesx($canvas);
$image_height = imagesy($canvas);
$iis =  $this->compute_ii($canvas, $image_width, $image_height);
return array(
'width' => $image_width,
'height' => $image_height,
'ii' => $iis['ii'],
'ii2' => $iis['ii2']
);
}

protected function compute_ii($canvas, $image_width, $image_height ){
$ii_w = $image_width+1;
$ii_h = $image_height+1;
$ii = array();
$ii2 = array();

for($i=0; $i<$ii_w; $i++ ){
$ii[$i] = 0;
$ii2[$i] = 0;
}

for($i=1; $i<$ii_w; $i++ ){
$ii[$i*$ii_w] = 0;
$ii2[$i*$ii_w] = 0;
$rowsum = 0;
$rowsum2 = 0;
for($j=1; $j<$ii_h; $j++ ){                 $rgb = ImageColorAt($canvas, $j, $i);                 $red = ($rgb >> 16) &amp;amp; 0xFF;
$green = ($rgb >> 8) &amp;amp; 0xFF;
$blue = $rgb &amp;amp; 0xFF;
$grey = ( 0.2989*$red + 0.587*$green + 0.114*$blue )>>0;  // this is what matlab uses
$rowsum += $grey;
$rowsum2 += $grey*$grey;

$ii_above = ($i-1)*$ii_w + $j;
$ii_this = $i*$ii_w + $j;

$ii[$ii_this] = $ii[$ii_above] + $rowsum;
$ii2[$ii_this] = $ii2[$ii_above] + $rowsum2;
}
}
return array('ii'=>$ii, 'ii2' => $ii2);
}

protected function do_detect_greedy_big_to_small( $ii, $ii2, $width, $height ){
$s_w = $width/20.0;
$s_h = $height/20.0;
$start_scale = $s_h < $s_w ? $s_h : $s_w;         $scale_update = 1 / 1.2;         for($scale = $start_scale; $scale > 1; $scale *= $scale_update ){
$w = (20*$scale) >> 0;
$endx = $width - $w - 1;
$endy = $height - $w - 1;
$step = max( $scale, 2 ) >> 0;
$inv_area = 1 / ($w*$w);
for($y = 0; $y < $endy ; $y += $step ){
for($x = 0; $x < $endx ; $x += $step ){                     $passed = $this->detect_on_sub_image( $x, $y, $scale, $ii, $ii2, $w, $width+1, $inv_area);
if( $passed ) {
return array('x'=>$x, 'y'=>$y, 'w'=>$w);
}
} // end x
} // end y
}  // end scale
return null;
}

protected function detect_on_sub_image( $x, $y, $scale, $ii, $ii2, $w, $iiw, $inv_area){
$mean = ( $ii[($y+$w)*$iiw + $x + $w] + $ii[$y*$iiw+$x] - $ii[($y+$w)*$iiw+$x] - $ii[$y*$iiw+$x+$w]  )*$inv_area;
$vnorm =  ( $ii2[($y+$w)*$iiw + $x + $w] + $ii2[$y*$iiw+$x] - $ii2[($y+$w)*$iiw+$x] - $ii2[$y*$iiw+$x+$w]  )*$inv_area - ($mean*$mean);
$vnorm = $vnorm > 1 ? sqrt($vnorm) : 1;

$passed = true;
for($i_stage = 0; $i_stage < count($this->detection_data); $i_stage++ ){
$stage = $this->detection_data[$i_stage];
$trees = $stage[0];

$stage_thresh = $stage[1];
$stage_sum = 0;

for($i_tree = 0; $i_tree < count($trees); $i_tree++ ){
$tree = $trees[$i_tree];
$current_node = $tree[0];
$tree_sum = 0;
while( $current_node != null ){
$vals = $current_node[0];
$node_thresh = $vals[0];
$leftval = $vals[1];
$rightval = $vals[2];
$leftidx = $vals[3];
$rightidx = $vals[4];
$rects = $current_node[1];

$rect_sum = 0;
for( $i_rect = 0; $i_rect < count($rects); $i_rect++ ){                         $s = $scale;                         $rect = $rects[$i_rect];                         $rx = ($rect[0]*$s+$x)>>0;
$ry = ($rect[1]*$s+$y)>>0;
$rw = ($rect[2]*$s)>>0;
$rh = ($rect[3]*$s)>>0;
$wt = $rect[4];

$r_sum = ( $ii[($ry+$rh)*$iiw + $rx + $rw] + $ii[$ry*$iiw+$rx] - $ii[($ry+$rh)*$iiw+$rx] - $ii[$ry*$iiw+$rx+$rw] )*$wt;
$rect_sum += $r_sum;
}

$rect_sum *= $inv_area;

$current_node = null;
if( $rect_sum >= $node_thresh*$vnorm ){
if( $rightidx == -1 )
$tree_sum = $rightval;
else
$current_node = $tree[$rightidx];
} else {
if( $leftidx == -1 )
$tree_sum = $leftval;
else
$current_node = $tree[$leftidx];
}
}
$stage_sum += $tree_sum;
}
if( $stage_sum < $stage_thresh ){
return false;
}
}
return true;
}
}

To use the code you will require a specific DAT file: http://svay.com/experiences/face-detection/detection.dat , the DAT file should be in the same folder as the piece of code as above, if this is not possible you will need to set the location in the piece of PHP code to follow.

Whenever you want to highlight a face in a picture run this piece of PHP code:


$detector = new Face_Detector('detection.dat');
$detector->face_detect('myface.jpg');
$detector->toJpeg();

Change the “myface.jpg” string to the image you wish to check. The result will look something like this:

detection

If you require a true or false response then return “$passed” instead and remove the line that outputs the jpeg image. This code is very useful and could be used for many purposes including:

  • Checking ID card photos (if the code can’t find the face the picture may not be clear enough)
  • Sorting images into people and places
  • Check if images taken by a webcam contain a face

If you have any suggestions about the code or any other ideas of its uses, let us know!

Comments (1)

[...] the original: Cardboard Coder » Blog Archive » Face Detection with PHP Posted in Object. Tags: cardboard-coder, code, face-detection-with-php, facebook, featured-posts, [...]

Write a comment