有没有人知道在
PHP中进行面部检测的好办法?
I came across some code here声称这样做,但我似乎无法使其正常工作.我想做这个工作(即使它会很慢),任何你可以给我的帮助将是非常感激的.
原文链接:https://www.f2er.com/php/139293.html<?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 // karthik_tharavaad@yahoo.com // @Contributor Maurice Svay // maurice@svay.Com 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,$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['height']); } return ($this->face['w'] > 0); } public function toJpeg() { $color = imagecolorallocate($this->canvas,255,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_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,$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,$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)到文件的顶部(不是真的解决方案),它似乎有时工作,而其他时候,它根本没有做任何事情.
有什么想法吗?