在PHP / GD中查找另一个图像内的图像的方法?

时间:2016-03-15 04:38:43

标签: php image-processing gd

我需要一种方法来在PHP / gd中找到另一个图像中图像的位置。 例如,找到此图片:

enter image description here

在此图片中:

so_big.png

我尝试自己创建一个函数来做到这一点,我很成功,但是速度非常慢,对于我来说,使用上面的示例图片需要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;
}

0 个答案:

没有答案