我需要一种方法来在PHP / gd中找到另一个图像中图像的位置。 例如,找到此图片:
在此图片中:
我尝试自己创建一个函数来做到这一点,我很成功,但是速度非常慢,对于我来说,使用上面的示例图片需要50%的CPU,我不知道如何优化它(如果可能的话)进一步。那么有更快的方法吗?最好更快? (例如,Auto Hotkey可以在具有此功能https://autohotkey.com/docs/commands/ImageSearch.htm的同一台计算机上的<2秒内执行相同的操作)
编辑:我想我可以通过imagecolorexact通过大图像的颜色索引创建小图像的副本,这允许2件事,检测小图像有没有像素的情况存在于大图像中,无法进行匹配,比较int(x)===int(x)
比比较array("red"=>x,"green"=>x,"blue"=>x)==array("red"=>x,"green"=>x,"blue"=>x)
要快得多 - 看起来速度几乎是三倍,使用前30秒,现在使用9秒。仍然无法接近AutoHotKey的速度:/
$big = imagecreatefrompng ( 'so_big.png' );
$small = imagecreatefrompng ( 'so_small.png' );
bench ( __LINE__ );
var_dump ( FindImageInImageV2 ( $big, $small) );
bench ( __LINE__ );
die ( "DONED" );
function FindImageInImageV2($big, $small, int $max = PHP_INT_MAX,bool $center=true): array {
assert ( is_resource ( $small ) );
assert ( is_resource ( $big ) );
$ret = array ();
//think2 ( $big, 'FindImageInImage/big' );
//think2 ( $small, 'FindImageInImage/small' );
$smallx = imagesx ( $small );
$smally = imagesy ( $small );
$bigx = imagesx ( $big );
$bigy = imagesy ( $big );
assert ( $bigx >= $smallx );
if ($bigx < $smallx) {
return $ret; // match is impossible
}
assert ( $bigy >= $smally );
if ($bigy < $smally) {
return $ret; // match is impossible
}
$smallcolors = imagecolorstotal ( $small );
$bigcolors = imagecolorstotal ( $big );
// assert($smallcolors<$bigcolors);
if ($smallcolors > $bigcolors) {
return $ret; // too many colors, match is impossible.
}
$smallImageAsColors = array ();
for($x = 0; $x < $smallx; ++ $x) {
$smallImageAsColors [$x] = array ();
for($y = 0; $y < $smally; ++ $y) {
$tmp = imagecolorsforindex ( $small, imagecolorat ( $small, $x, $y ) );
//unset ( $tmp ['alpha'] );
$tmp=imagecolorexact ( $big, $tmp['red'], $tmp['green'],$tmp['blue']);
if($tmp===-1){
//small has a color that does not exist in big, match is impossible
return $ret;
}
$smallImageAsColors [$x] [/*$y*/] = $tmp;
}
}
unset ( $x, $y, $tmp );
for($x = 0; $x < $bigx; ++ $x) {
if ($bigx < ($x + $smallx)) {//<< todo: can be optimized away.
break; // too close to the end, no result possible..
}
for($y = 0; $y < $bigy; ++ $y) {
if ($bigy < ($y + $smally)) {//<< todo: can be optimized away.
continue; // too close to the bottom, no result possible for this $y..
}
//$matchFound = true;
for($i = 0; $i < $smallx; ++ $i) {
for($ii = 0; $ii < $smally; ++ $ii) {
// yelp
if($smallImageAsColors [$i][$ii]!==imagecolorat($big,$x+$i,$y+$ii))
{
//$matchFound=false;
//goto outofmatching;//i can micro optimize the jumps more actually... but should i?
//goto uglyoptimize;
continue 3;
}
}
}
//outofmatching:
//if ($matchFound) {
$ret [] = array (
'x' => ($center?$x+((int)floor($smallx/2)):$x),
'y' => ($center?$y+((int)floor($smally/2)):$y)
);
if (count ( $ret ) >= $max) {
//goto done;
return $ret;
}
//}
//uglyoptimize:
}
}
//done:
return $ret;
}