Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
80 views
in Technique[技术] by (71.8m points)

php - Group color zones in an image

I have this image that my PHP generates from data. this image

Now, it has a few distinct coloured zones. Each of these zones must be placed into a separate array of pixel points. At the moment all pixels with their colors are in a single width x height array. So it needs to be subdivided.

The human eye can distinguish the zones immediately and trace the outline of each zone. How do I approach this in PHP?

One way I thought to do this is to step through every row and column - and as soon as the color of two adjacent pixels differs, to create a type of a "while" based function which will go on searching for a color equality in all 4 directions. I am just worried that all these nested iterations will slow down my execution considerably.

question from:https://stackoverflow.com/questions/65950426/group-color-zones-in-an-image

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I don't use PHP much any more, but as you aren't getting any answers, I'll put some thoughts and maybe someone else can improve or correct me.

I think the best approach is probably to use "Connected Component Analysis", related to and variously known as "labelling" and "Blob Analysis". You can do that with ImageMagick as shown here, which would require you to "shell out" to the command-line using system() because I do not think it is available in PHP Imagick.

For your image, I ran:

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

The output image is shown below, and as you can see each of your blobs is "labelled" with a successively lighter shade of grey (higher number) and even blobs of the same colour get a unique label as long as they are not touching.

Output

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)

I then outlined the 5th last line from above that looks like this:

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

That means a 288 px wide by 172 px tall rectangle with its top-left corner at coordinates [464,448]. You can also see coordinates of the centroid, area at 33440 pixels and the colour is red.

I used this to draw the outline in cyan - note that draw requires top-left and bottom-right rather than top-left and width and height:

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

enter image description here


There are PHP bindings for libvips too, and I think you'd want the labelregions function.


Failing that, you could use this approach:

  • identify the list of unique colours in the image
  • iterate over that list, repeatedly finding the first pixel of that colour and calling a floodfill, starting from that pixel, to make pixels of that colour say "black", then chop out all the black pixels and find the next pixel of the current unique colour till there are no more pixels of that colour
  • repeat until there are no more unique colours.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...