2015-02-01 2 views
0

Моя цель с помощью этого скрипта - сделать интеллектуальные миниатюры. В моем демо-пакете я использую два сценария из разных источников.Миниатюры с распознаванием лиц в PHP

  1. Для кадрирования миниатюры (Source) - Это полностью работает как родная WordPress иконки
  2. Распознавание лиц в PHP (Source)

Я использую функцию обнаружение лица, чтобы получить желаемые координаты (где лицо), а затем передать координаты сценарию обрезки, чтобы сделать эскиз.

Проблема заключается в том, если сценарий обнаружения лица не находит лицо, она бы просто тайм-аут с тайм-аут ошибки

Fatal error: Maximum execution time of 30 seconds exceeded in...

Я не знаю, как прийти вокруг этого вопроса. Есть ли способ ограничить время обнаружения детектора лица? Я имею в виду, если он не найден в течение 15 секунд, верните нуль.

Вот код обнаружения лица:

<?php 
// 
// This program is free software; you can redistribute it and/or 
// modify it under the terms of the GNU General Public License 
// 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] 

namespace svay; 

use Exception; 

class FaceDetector 
{ 

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

    /** 
    * Creates a face-detector with the given configuration 
    * 
    * Configuration can be either passed as an array or as 
    * a filepath to a serialized array file-dump 
    * 
    * @param string|array $detection_data 
    */ 
    public function __construct($detection_data = 'detection.dat') 
    { 
     if (is_array($detection_data)) { 
      $this->detection_data = $detection_data; 
      return; 
     } 

     if (!is_file($detection_data)) { 
      // fallback to same file in this class's directory 
      $detection_data = dirname(__FILE__) . DIRECTORY_SEPARATOR . $detection_data; 

      if (!is_file($detection_data)) { 
       throw new \Exception("Couldn't load detection data"); 
      } 
     } 

     $this->detection_data = unserialize(file_get_contents($detection_data)); 
    } 

    public function faceDetect($file) 
    { 
     if (is_resource($file)) { 

      $this->canvas = $file; 

     } elseif (is_file($file)) { 

      //getting extension type (jpg, png, etc) 
      $type = explode(".", $file); 
      $ext = strtolower($type[sizeof($type)-1]); 
      $ext = (!in_array($ext, array("jpeg","png","gif"))) ? "jpeg" : $ext; 

      if ($ext == 'jpeg') { 
       $this->canvas = imagecreatefromjpeg($file); 
      } else if ($ext == 'png') { 
       $this->canvas = imagecreatefrompng($file); 
      } else if ($ext == 'gif') { 
       $this->canvas = imagecreatefromgif($file); 
      } 

     } else { 

      throw new Exception("Can not load $file"); 
     } 

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

     //Resample before detection? 
     $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->getImgStats($this->reduced_canvas); 

      $this->face = $this->doDetectGreedyBigToSmall(
       $stats['ii'], 
       $stats['ii2'], 
       $stats['width'], 
       $stats['height'] 
      ); 

      if ($this->face['w'] > 0) { 
       $this->face['x'] *= $ratio; 
       $this->face['y'] *= $ratio; 
       $this->face['w'] *= $ratio; 
      } 
     } else { 
      $stats = $this->getImgStats($this->canvas); 

      $this->face = $this->doDetectGreedyBigToSmall(
       $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 json_encode($this->face); 
    } 

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

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

    protected function computeII($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_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; 
      } 
     } 
     return array('ii'=>$ii, 'ii2' => $ii2); 
    } 

    protected function doDetectGreedyBigToSmall($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->detectOnSubImage($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 detectOnSubImage($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; 

     $count_data = count($this->detection_data); 

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

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

      $count_trees = count($trees); 

      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; 
        $count_rects = count($rects); 

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

Вот пример использования:

include "facedetection/FaceDetector.php"; 

$detector = new svay\FaceDetector('detection.dat'); 
$detector->faceDetect($path); 
$coord = $detector->getFace(); 

Любая помощь или предложить другие PHP эскизы с помощью сценария обнаружения лица.

+0

В Unix-подобной системе вы можете использовать [getrusage()] (http://php.net/getrusage) для отслеживания времени выполнения, или вы можете просто отслеживать время с помощью [microtime()] (http: // php.net/manual/en/function.microtime.php) для отслеживания прошедшего времени. Реальная проблема здесь заключается в том, чтобы использовать PHP для обработки процессоров с интенсивной графикой - это просто не инструмент для этой работы. –

ответ

0

Можете ли вы увеличить срок? Вы можете использовать set_time_limit() или изменить свой php.ini, если у вас есть к нему доступ. Кроме того, насколько велика файл detect.dat? Загрузка файла целиком в файл с файлом_get_contents() может занять некоторое время, если файл большой.

Если вы не испортили код FaceDetection (который не рекомендуется, если вы не захотите обновлять библиотеку), вы не сможете остановить выполнение через 15 секунд. Они не предоставляют никаких крючков, где вы могли бы сказать, что сценарий остановлен.

+0

Проблема заключается не в том, чтобы время, затрачиваемое на выполнение, а на фактическую проблему, заключается в том, что сценарий никогда не находит лицо, и он просто продолжает искать лицо. – Junaid

Смежные вопросы