2010-11-11 20 views
12

Kennt jemand eine gute Möglichkeit, Gesichtserkennung in PHP zu tun? I came across some code here das behauptet, dies zu tun, aber ich kann nicht scheinen, damit es richtig funktioniert. Ich würde gerne diese Arbeit machen (obwohl es langsam wird) und jede Hilfe, die Sie mir geben können, wäre sehr geschätzt.Gesichtserkennung in PHP

Hier ist der Code aus dem Link:

<?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; 
    } 
} 

Verbrauch:

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

Das Problem, das ich in laufen lasse, scheint in den Kommentaren auch auf dieser Seite kommen zu werden. "imagecolorat() [function.imagecolorat]: 320,1 ist außerhalb der Grenzen." Also, ich habe eine Fehlermeldung (0) an den Anfang der Datei (nicht wirklich die Lösung) hinzugefügt, und es scheint manchmal zu arbeiten, während es manchmal einfach nichts tut.

Irgendwelche Gedanken?

+0

möglich Duplikat [Gesichtserkennung/dete ction PHP oder Software für Foto- und Videogalerien] (http://stackoverflow.com/questions/1210672/facial-recognition-detection-php-o--software-for-photo-and-video-galerien) – Gordon

Antwort

1

Versuchen Sie, die einen aus diesen Linien zu entfernen:

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

Dieser Code versucht, die Farben von den Positionen 1 bis 320 anstelle von 0 bis 319 in dem 320 Pixelbild zu überprüfen.

+0

Ich dachte, dass als gut, aber ich bekomme immer noch die gleiche Nachricht. Ich denke, die Parameter sind auch im Funktionsaufruf ImageColorAt rückwärts, aber wenn ich sie umschalte, bekomme ich einen "undefinierten Offsetfehler" in der Zeile "$ mean = ($ ii [($ y + $ w) * $ iiw + $" x + $ w] + $ ii [$ y * $ iiw + $ x] - $ ii [($ y + $ w) * $ iiw + $ x] - $ ii [$ y * $ iiw + $ x + $ w]) * $ inv_area; " –

3

Es wäre wahrscheinlich einfacher/sicherer, dies mit OpenCV zu tun, die in niedrigerer Code geschrieben wird. PHP wird interpretiert, also wird es wahrscheinlich hella langsam sein, wenn Sie den Job machen.

Hoffe, das hilft!

+0

Ich suche nach einer Antwort, die nicht so etwas wie OpenCV beinhaltet.Trotzdem danke! –

3

Sie müssen Fehler auszuschalten Berichterstattung

<?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

Ich denke, das vermisst den Punkt. –

+2

Da Sie ein Bild erzeugen, benötigt es keine Php-Warnmeldungen, die im Ergebnis angezeigt werden, da es die Bilddatei beschädigt und nicht angezeigt wird. Genau das passierte mit meiner Implementierung. Und das Ergebnis gibt manchmal Warnmeldungen, so dass das Deaktivieren von Fehlerberichten mir geholfen hat. – vhanla

0

Quick Fix: in der compute_ii Funktion

ersetzen:

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

mit:

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

Dies ist ein altes Thema, aber immer noch dieses Update ist besser als alles, was ich so bisher sah, könnte es jemand

// 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

Das Projekt auf Github-Repository helfen, indem Sie den Link Face detection

Die aktualisiert wurde Problem auf der Schleife war, dieser Code funktioniert:

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; 
     } 
    } 

Viel Glück