Как можно ускорить это код php:
<?php
class HalFaceRec {
protected $detection_data;
protected $img;
protected $face;
private $reduced_img;
public function __construct() {
$this->detection_data = unserialize(file_get_contents('detection.dat'));
}
public function getImgStats($img) {
$imgw = imagesx($img);
$imgh = imagesy($img);
$iis = $this->computeII($img,$imgw,$imgh);
return [
'width'=>$imgw,
'height'=>$imgh,
'ii'=>$iis['ii'],
'ii2'=>$iis['ii2']
];
}
public function computeII($img,$imgw,$imgh) {
$ii_w = $imgw+1;
$ii_h = $imgh+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($img, $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 ['ii'=>$ii, 'ii2' => $ii2];
}
public function detectOnSubImage($x,$y,$scale,$ii,$ii2,$w,$iiw,$inv_area,$count_data) {
$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;
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;
}
public function detectGreedyBigToSmall($ii,$ii2,$width,$height,$s_w,$s_h) {
$start_scale = $s_h < $s_w ? $s_h : $s_w;
$scale_update = 1 / 1.2;
$count_data = count($this->detection_data);
$out = [];
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,$count_data);
if ($passed) {
$out[] = ['x'=>$x, 'y'=>$y, 'w'=>$w];
}
} // end x
} // end y
} // end scale
return $out;
}
public function faceDetect($img) {
if (is_resource($img)) {
$this->img = $img;
} else if (is_file($img)) {
$ex = explode('.',$img);
$ex = $ex[count($ex)-1];
if ($ex == 'png') {
$this->img = imagecreatefrompng($img);
} else if ($ex == 'bmp') {
$this->img = imagecreatefrombmp($img);
} else {
$this->img = imagecreatefromjpeg($img);
}
} else if (is_string($img)) {
$this->img = imagecreatefromstring($img);
} else {
throw new Exception("Can't load your image");
}
$imgw = imagesx($this->img);
$imgh = imagesy($this->img);
$diffw = 320 - $imgw;
$diffh = 240 - $imgh;
if ($diffw > $diffh) {
$ratio = $imgw / 320;
} else {
$ratio = $imgh / 240;
}
if ($ratio != 0) {
$this->reduced_img = imagecreatetruecolor($imgw/$ratio,$imgh/$ratio);
imagecopyresampled(
$this->reduced_img,
$this->img,
0,
0,
0,
0,
$imgw/$ratio,
$imgh/$ratio,
$imgw,
$imgh
);
$stats = $this->getImgStats($this->reduced_img);
$this->face = $this->detectGreedyBigToSmall(
$stats['ii'],
$stats['ii2'],
$stats['width'],
$stats['height'],
$stats['width']/20,
$stats['height']/20
);
if (count($this->face) > 0) {
for ($i = 0; $i < count($this->face); $i++) {
$this->face[$i]['x'] *= $ratio;
$this->face[$i]['y'] *= $ratio;
$this->face[$i]['w'] *= $ratio;
}
}
return $this->face;
} else {
$stats = $this->getImgStats($this->img);
$this->face = $this->detectGreedyBigToSmall(
$stats['ii'],
$stats['ii2'],
$stats['width'],
$stats['height'],
$stats['width']/20,
$stats['height']/20
);
return $this->face;
}
}
public function draw($img,$result) {
$color = imagecolorallocate($img,255,0,0);
foreach ($result as $res) {
imagerectangle(
$img,
$res['x'],
$res['y'],
$res['x']+$res['w'],
$res['y']+$res['w'],
$color
);
}
return $img;
}
public function cropFace($img,$result) {
$res = $result[0];
$thumb = imagecreatetruecolor($res['w'],$res['w']);
imagecopy($thumb,$img,0,0,$res['x'],$res['y'],$res['w'],$res['w']);
return $thumb;
}
}
$facerec = new HalFaceRec();
if (!empty($_GET['req']) and !empty($_FILES['img'])) {
$req = $_GET['req'];
if ($req == 'detectAndDraw') {
$img = imagecreatefromjpeg($_FILES['img']['tmp_name']);
header('Content-Type: image/jpeg');
imagejpeg($facerec->draw($img,$facerec->faceDetect($img)));
} else if ($req == 'detectAndCrop') {
$img = imagecreatefromjpeg($_FILES['img']['tmp_name']);
header('Content-Type: image/jpeg');
imagejpeg($facerec->cropFace($img,$facerec->faceDetect($img)));
}
}
?>