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
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.