在PHP中使用GD检测图像中的岛屿


Detecting islands in image with GD in PHP

我正在研究一个PHP图像处理库,该库与游戏中的渲染图像一起工作,在PHP网站主机上进行处理。为了处理图像,我需要找到红色岛屿(色调在x值为0或360的地方),并在其中找到一个点(不一定是中心,但最好靠近中心)。这样的岛屿大约有100个,大小不一。它们是梯形或接近梯形。由于该图像是PNG格式,并且未经压缩而没有抗锯齿,因此边缘对像素来说是清晰的,但某些区域可能比其他区域更暗。

目前,我所尝试的是在GD中使用imagecolorat(并在转换后测试HSV值,然后在它周围尝试点,直到我达到非红色像素,但该过程似乎需要一些时间才能完成,并且由于5秒的限制似乎遇到PHP超时,如果我正在处理一个大图像。有没有一种更有效的方法来探测这些岛屿,并得到一个点,不一定是在中心,但更可取的是在附近?

我也试过,我知道梯形的大小,假设没有一个在一定距离内,跳过这个距离以节省时间。

我不需要代码,只需要一个指向正确方向的指针。

我的当前代码:

function RGBToHSL($RGB) {
    $r = 0xFF & ($RGB >> 0x10);
    $g = 0xFF & ($RGB >> 0x8);

//剪断}

$image=imagecreatefrompng($filename);
$redislands=[];
for($xpos=0; $xpos<=imagesx($image); $xpos++){
    for($ypos=0; $ypos<=imagesy($image); $ypos++){
        if (RGBToHSL(imagecolorat(xpos, ypos)->saturation<=20||RGBToHSL(imagecolorat(xpos, ypos)->saturation>=350){
            $redislands[]=[xpos, ypos]
            }
        }
    }

我从来没有真正使用过gd,但我只是简单地看了一下,我看到

imagefilter() w/IMG_FILTER_EDGEDETECT标志。

之后,你可以用一个简单的循环来识别所有的对象(如果对象有一个最小大小,你可以让循环使用这个条带大小,仍然保证你会遇到每个对象)。只是寻找一个像素w/边缘颜色,当你找到一个,递归探索相邻像素w/边缘颜色。例如,如果一个对象保证至少有7个像素高,在突出显示边缘后,您只需要循环遍历第0、7、14、21行等像素…

一旦你使用它周围的边缘提取组件,我想你可以很容易地识别它的形状,颜色和中心。

如果边缘没有被检测到,你可能需要对图像进行阈值设置(gd可以这样做)。

另一个需要认真考虑的选择是不使用php,而是使用php的exec()函数执行外部程序。这打开了使用各种库(如opencv)和程序的可能性。它还允许你用c之类的语言编写代码…您可能会惊讶于循环一个c数组的速度有多快,该数组包含几百万个表示像素颜色的整数。但是,我有一种感觉,这对你来说不是一个可行的选择。

您可能还会研究访问php数组(或字符串)的像素。函数调用开销很大,与$pixels[$i]这样的本地php数组访问相比,数百万次调用imagecolorat()这样的函数会增加开销。我对图像格式一无所知,但也许你可以保存为位图,然后加载到字符串中,然后使用字符串偏移量。我敢打赌,如果位图具有合适的类似数组的二进制表示,那么它将会飞起来。