2010-11-11 105 views
12

有谁知道在PHP中进行人脸检测的好方法吗? I came across some code here声称这样做,但我似乎无法让它正常工作。我想做这个工作(尽管它会很慢),任何帮助你可以给我会非常感激。PHP中的人脸检测

下面是来自链接代码:

<?php 
// as published by the Free Software Foundation; either version 2 
// of the License, or (at your option) any later version. 
// 
// This program is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
// GNU General Public License for more details. 
// 
// You should have received a copy of the GNU General Public License 
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  
// 
// @Author Karthik Tharavaad 
//   [email protected] 
// @Contributor Maurice Svay 
//    [email protected] 

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) & 0xFF; 
       $green = ($rgb >> 8) & 0xFF; 
       $blue = $rgb & 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; 
    } 
} 

用法:

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

我遇到的问题,似乎在页面上的注释中来了也。 “imagecolorat()[function.imagecolorat]:320,1超出范围。”所以,我在文件的顶部添加了一个error_reporting(0)(不是真正的解决方案),而且有时它似乎有效,而其他时候它不会执行任何操作。

有什么想法?

+0

可能重复ction PHP或软件的照片和视频画廊](http://stackoverflow.com/questions/1210672/facial-recognition-detection-php-or-software-for-photo-and-video-galleries) – Gordon 2010-11-12 08:20:05

回答

1

尝试删除从这些行的1:

$ii_w = $image_width+1; 
$ii_h = $image_height+1; 

此代码试图从320像素的图像中的位置1至320,而不是0到319检查颜色。

+0

我认为,作为好吧,但我仍然得到相同的信息。我认为参数在ImageColorAt函数调用中也是向后的,但是当我切换它们时,我会在“$ mean =($ ii [($ y + $ w)* $ iiw + $ x $ w $ + $ ii $ $ $ iiw + $ x $ ii $($ y + $ w)* $ iiw + $ x] - $ ii [$ y * $ iiw + $ x + $ w])* $ inv_area;” – 2010-11-11 22:47:48

3

OpenCV这样做可能会更简单/更安全,这是用较低级代码编写的。 PHP被解释,所以在做这项工作时可能会很慢。

希望这会有所帮助!

+0

我正在寻找一个不涉及OpenCV之类的答案。虽然谢谢! – 2010-11-12 01:41:05

3

您需要关闭错误报告

<?php 

ini_set('display_errors', 1); 
error_reporting(E_ALL^E_NOTICE); 

require_once('face_detector.php'); 

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

?> 
+1

我认为这错过了观点。 – 2012-02-21 15:43:07

+2

由于您正在生成一张图片,因此它不需要显示php警告消息,因为它会损坏图像文件而不会显示。这正是我实施过程中发生的情况。结果有时会给出警告消息,因此禁用错误报告对我有帮助。 – vhanla 2012-05-11 18:09:50

0

快速修复:在compute_ii功能

替换:

$rgb = ImageColorAt($canvas, $j, $i); 

有了:

$rgb = ImageColorAt($canvas, $j-1, $i-1); 
0

这是一个老话题,但仍然此修复程序是比任何我看到到目前为止,一切都更好,这可能会帮助别人

// Turn off error reporting... 
$ctl = error_reporting(); 
error_reporting(0); 

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

// Turn on reporting...if you wish 
error_reporting($ctl); 
0

该项目已通过以下链接Face detection

升级GitHub上库问题是环路,该代码工作正常:

for ($i=1; $i<$ii_h-1; $i++) { 
     $ii[$i*$ii_w] = 0; 
     $ii2[$i*$ii_w] = 0; 
     $rowsum = 0; 
     $rowsum2 = 0; 
     for ($j=1; $j<$ii_w-1; $j++) { 
      $rgb = ImageColorAt($canvas, $j, $i); 
      $red = ($rgb >> 16) & 0xFF; 
      $green = ($rgb >> 8) & 0xFF; 
      $blue = $rgb & 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; 
     } 
    } 

好运

[面部识别/ DETE的