如何在PHP/GD中找到另一个图像中的图像?
我需要一种在PHP/gd中查找另一个图像中的图像位置的方法。 例如,找到此图像: 在此图像中: 我试着自己做一个函数来完成这项工作,我成功了,但速度非常慢,上面的示例图片显示,在100%CPU的情况下,我需要50秒以上的时间,我不知道如何进一步优化它(如果可能的话)。那么有什么方法可以更快地做到这一点吗?最好快一点?(例如,自动热键可以在x中执行相同的操作,“绿色”=>x,“蓝色”=>x)==array(“红色”=>x,“绿色”=>x,“蓝色”=>x)——这样看起来速度几乎是原来的三倍,现在是9秒。但仍远不及AutoHotKey的速度:/如何在PHP/GD中找到另一个图像中的图像?,php,image-processing,gd,Php,Image Processing,Gd,我需要一种在PHP/gd中查找另一个图像中的图像位置的方法。 例如,找到此图像: 在此图像中: 我试着自己做一个函数来完成这项工作,我成功了,但速度非常慢,上面的示例图片显示,在100%CPU的情况下,我需要50秒以上的时间,我不知道如何进一步优化它(如果可能的话)。那么有什么方法可以更快地做到这一点吗?最好快一点?(例如,自动热键可以在x中执行相同的操作,“绿色”=>x,“蓝色”=>x)==array(“红色”=>x,“绿色”=>x,“蓝色”=>x)——这样看起来速度几乎是原来的三倍,现在
$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;
}
$big=imagecreatefrompng('so_big.png');
$small=imagecreatefrompng('so_small.png');
工作台(直线);
var_dump(FindImageInImageV2($big,$small));
工作台(直线);
死亡(“被骗”);
函数FindImageInImageV2($big,$small,int$max=PHP\u int\u max,bool$center=true):数组{
断言(is_资源($small));
断言(is_资源($big));
$ret=array();
//think2($big,'findimageminimage/big');
//think2($small,'FindImageInImage/small');
$smallx=imagesx($small);
$smally=imagesy($small);
$bigx=imagesx($big);
$bigy=imagesy($big);
断言($bigx>=$smallx);
如果($bigx<$smallx){
return$ret;//不可能匹配
}
断言($bigy>=$smally);
如果($bigy<$smally){
return$ret;//不可能匹配
}
$smallcolors=imagecolorstotal($small);
$bigcolors=imagecolorstotal($big);
//断言($smallcolors$bigcolors){
return$ret;//颜色太多,无法匹配。
}
$smallImageAsColors=array();
对于($x=0;$x<$smallx;++$x){
$smallImageAsColors[$x]=array();
对于($y=0;$y<$smally;++$y){
$tmp=imagecolorsforindex($small,imagecolorat($small,$x,$y));
//未结算($tmp['alpha']);
$tmp=imagecolorexact($big、$tmp['red']、$tmp['green']、$tmp['blue']);
如果($tmp==-1){
//小的有一种大的不存在的颜色,匹配是不可能的
返回$ret;
}
$smallImageAsColors[$x][/*$y*/]=$tmp;
}
}
未结算($x,$y,$tmp);
对于($x=0;$x<$bigx;++$x){
如果($bigx<($x+$smallx)){/($center?$y+((int)floor($smally/2)):$y)
);
如果(计数($ret)>=$max){
//去做;
返回$ret;
}
//}
//丑优化:
}
}
//完成:
返回$ret;
}
试着朝着pHash的方向挖掘:也检查一下这个:一些想法,但没有金弹If
语句阻塞了流水线处理流程,如果将前面for语句中的限制更改为for,则可以删除for($x
和for($y)循环中的第一个If
语句($x=0;$x当你开始计算两幅图像中的颜色时,你可能会在你的小图像中得到两种最稀有的颜色&而不是通过从左上到右下依次遍历小图像中的像素来尝试内部循环中的匹配,你可以从上到下检查2-3种最稀有颜色的位置nt&在进入主循环之前,可能会很快地拒绝子图像。或者可能会检查四个角和中间,这也可能会更快地拒绝,特别是如果图像左上角是白色的,则大图像有大面积的白色。另一个想法是减小图像的大小,并尝试与f的互相关找到可能的匹配项进行进一步调查。@MarkSetchell谢谢!我肯定会对if()进行优化,但其他建议听起来很难,我现在不想研究这些建议,但我下次尝试优化时会再讨论^^