首页 > 解决方案 > 对图像中的颜色区域进行分组

问题描述

我有我的 PHP 从数据生成的这个图像。 这个图片

现在,它有几个不同的颜色区域。这些区域中的每一个都必须放置在单独的像素点阵列中。目前,所有像素及其颜色都在一个宽度 x 高度数组中。所以需要细分。

人眼可以立即区分区域并追踪每个区域的轮廓。我如何在 PHP 中解决这个问题?

我认为这样做的一种方法是遍历每一行和每一列——一旦两个相邻像素的颜色不同,就创建一种基于“while”的函数,它将继续搜索所有颜色的相等性4个方向。我只是担心所有这些嵌套迭代会大大减慢我的执行速度。

标签: phparraysimagecolorspixel

解决方案


我不再使用PHP,但是由于您没有得到任何答案,我会提出一些想法,也许其他人可以改进或纠正我。

我认为最好的方法可能是使用"Connected Component Analysis",与 "labelling" 和 "Blob Analysis" 相关,并被称为"labelling""Blob Analysis"。您可以使用ImageMagick来做到这一点,如此处所示,这将要求您使用“外壳”到命令行,system()因为我认为它在PHP Imagick中不可用。

为了你的形象,我跑了:

magick Pw7vC.png                                     \
    -define connected-components:verbose=true        \
    -define connected-components:area-threshold=100  \
    -connected-components 8 -auto-level output.png

输出图像如下所示,正如您所见,每个 blob 都被“标记”为逐渐变浅的灰色阴影(更高的数字),即使是相同颜色的 blob,只要它们不接触,它们也会获得唯一的标签。

输出

Objects (id: bounding-box centroid area mean-color):
  3: 752x808+0+16 425.8,374.4 317264 srgba(255,255,0,1.20656)
  4: 296x680+0+96 125.2,459.3 156368 srgba(0,175,0,1.41911)
  9: 440x156+304+672 528.7,759.9 49776 srgba(255,0,0,2.3166)
  2: 774x850+0+0 578.4,612.6 48780 srgba(255,255,255,2.34348)
  1: 620x124+120+0 494.6,41.7 42208 srgba(255,0,0,2.55267)
  7: 288x172+464+448 608.6,522.8 33440 srgba(255,0,0,2.95978)
  5: 92x88+664+144 719.0,192.1 5008 srgba(0,175,0,14.0861)
  0: 264x40+0+0 72.5,10.9 3408 srgba(255,255,255,20.2298)
  8: 12x152+0+520 3.2,580.6 992 srgba(255,255,255,67.0635)
  6: 8x124+0+184 2.5,235.3 656 srgba(255,255,255,100.901)

然后我概述了上面的第 5 行,如下所示:

  7: 288x172+464+448 608.6,522.8 33440 srgba(255,0,0,2.95978)

这意味着一个 288 像素宽 x 172 像素高的矩形,其左上角位于坐标 [464,448]。您还可以看到质心的坐标,面积为 33440 像素,颜色为红色。

我用它来绘制青色轮廓 - 注意draw需要左上角和右下角而不是左上角和宽度和高度:

magick output.png -fill none -stroke cyan -draw "rectangle 464,448 752,620" result.png

在此处输入图像描述


libvips也有 PHP 绑定,我认为您需要labelregions函数。


如果做不到这一点,你可以使用这种方法:

  • 识别图像中唯一颜色的列表
  • 遍历该列表,重复查找该颜色的第一个像素并调用一个floodfill,从该像素开始,使该颜色的像素说“黑色”,然后切掉所有黑色像素并找到当前唯一的下一个像素颜色直到不再有该颜色的像素
  • 重复直到没有更多独特的颜色。

推荐阅读