PHP中的脸部检测

前端之家收集整理的这篇文章主要介绍了PHP中的脸部检测前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
有没有人知道在 PHP中进行面部检测的好办法? I came across some code here声称这样做,但我似乎无法使其正常工作.我想做这个工作(即使它会很慢),任何你可以给我的帮助将是非常感激的.

以下是链接中的代码

<?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)到文件的顶部(不是真的解决方案),它似乎有时工作,而其他时候,它根本没有做任何事情.

有什么想法吗?

使用较低级代码编写的 OpenCV可能会更容易/更安全. PHP被解释,所以在做这个工作时可能会很慢.

希望这可以帮助!

猜你在找的PHP相关文章