Gimp-Forum.net
Selecting one pixel from each blob in a binary image - Printable Version

+- Gimp-Forum.net (https://www.gimp-forum.net)
+-- Forum: GIMP (https://www.gimp-forum.net/Forum-GIMP)
+--- Forum: General questions (https://www.gimp-forum.net/Forum-General-questions)
+--- Thread: Selecting one pixel from each blob in a binary image (/Thread-Selecting-one-pixel-from-each-blob-in-a-binary-image)



Selecting one pixel from each blob in a binary image - cam92473 - 10-23-2024

Hi,

I have an image containing several white blobs on a black background. Using python fu, I was wondering the fastest and easiest way to select a single pixel from each of these white blobs (it doesn't have to be the center of each blob). I'm working with Gimp 3.0. Thanks in advance!


RE: Selecting one pixel from each blob in a binary image - Ofnuts - 10-23-2024

Can't tell for Gimp3, but for Gimp 2.10 I would do something like this:
  • Select by color the white: pdb.gimp_image_select_color()
  • Obtain a path from the selection pdb.plug_in_sel2path()
  • This gives you a path where each stroke is an envelope for each identified white blob
  • You can then use the coordinates of the anchors to compute an approximate centroid and round that value to get the coordinates of a pixel in the blob.



RE: Selecting one pixel from each blob in a binary image - cam92473 - 10-24-2024

Hi,

Thanks for your reply. Maybe I could clarify my objective, since you answered my specific question but I would still like some help with what I am doing, if possible.

I have two binary images, A and B, with white blobs on black backgrounds. I want to create an image that contains all the blobs in A that overlap (partially or completely) with blobs in B. So if a blob in B touches a blob in A, the A blob is kept in the final image. My first step so far has been to change the opacity of the top layer to create a new layer with 4 different colors (white, light gray, dark gray, and black), corresponding to the overlap states. From here, I can simply use the fuzzy select tool with the sample threshold set to a certain tolerance to select the white areas (the overlap), and that will select all the white and light gray areas, which corresponds to what I want. However, I am looking to automate this process, and if possible I'd like to avoid scripting a scenario where we have to click every white area (or a pixel in it) with the fuzzy select tool. I was looking for some sort of "local flooding" tool that could flood white areas locally into adjacent regions with a threshold. Or if there's some other approach that would work better I'm all ears. Ideally I would like it to be scriptable and not terribly computationally expensive, since I plan on doing this with a much larger image with many blobs. If you have any advice or ideas on how I can achieve my goal, I would be most grateful.

Image A:

[attachment=12482]

Image B:

[attachment=12481]

Resulting selection I want:

[attachment=12483]


RE: Selecting one pixel from each blob in a binary image - Ofnuts - 10-25-2024

I see two ways to do this.

Both start by selecting the white in A then getting a path form the selection, as explained previously (because this is the most practical way to separate the blobs in A). Once you have a path you can construct separate paths each with a copy of one stroke from the original (so one path per blob in A).

Then:
  • The first technique is to use each of these paths in turn to create a selection (so you have a selection mask which is one of the blobs in A) and use the pdb.gimp_drawable_histogram(...) on layer B to check for white (or non-black) pixels (the histogram applies to the selection).
  • A second technique is to extract path strokes from B (as you did for A) and check if any of these strokes intersects a stroke in A. Technically, you only need to find an anchor of the stroke of B which is inside a stroke of A. You can very quickly eliminate most candidates by checking that their bounding boxes don't intersect. If you want a bit more accuracy instead of the anchors you can use pdb.gimp_vectors_stroke_interpolate(...) to get a polygon with more summits.
Once you have determined if a stroke of A covers a blob in B using either method, you can either use the selection from the stroke to copy/recreate the blob on another layer, or grow it by one pixel and fill with black to obliterate a blob of A that doesn't overlap anything in B.

My ofn-path-edits script contains many examples of path extraction/splitting and checking nesting.


RE: Selecting one pixel from each blob in a binary image - rich2005 - 10-25-2024

This is a kubuntu 24.04 / Gimp 2.99.19 (appimage) It is the same in Gimp 2.10

As a non-programmer, a hands-on approach Wink

Using layer modes you can "mark" the relevant "blobs" but a selection (by color ) still includes all "blobs"

[attachment=12484]

A New-From-Visible gets the "marks" and a Filters -> Generic -> Dilate grows the white "blobs" into the selection. (ctrl-F a zillion times repeats the growth).

[attachment=12485]

Obviously very inefficient to use multiple dilates, maybe someone has a good way of growing the "blob" and deciding when the selection(s) are filled.

When it comes to Gimp 3 scripting, I despair. The devs seem intent on making it as difficult as possible for users who might occasionally dabble. This is what I have recently been looking at:
https://testing.docs.gimp.org/2.99/en/gimp-using-python-plug-in-tutorial.html
Seems very long-winded for a "hello world" plugin. The section before that is script-fu, which might be a better bet for Gimp 3 at the moment.


RE: Selecting one pixel from each blob in a binary image - MrsP-from-C - 10-25-2024

To get an idea of how a GIMP3 plug-in might look:
There is an example here:
https://gitlab.gnome.org/GNOME/gimp/-/blob/master/plug-ins/python/foggify.py

Not so bad, I think.


RE: Selecting one pixel from each blob in a binary image - rich2005 - 10-25-2024

Getting old and lost interest in most things these days. I am sure it will come as a matter of course eventually.

That is a good example but the Gimp 3 fog plugin is twice the size of the Gimp 2 fog plugin. Easy to see why when one line is replaced by eight.

Code:
----gimp2-------
    # add some clouds to the layer
    pdb.plug_in_plasma(img, mask, int(time.time()), turbulence)

----gimp3-------    
    # add some clouds to the layer
    pdb_proc   = Gimp.get_pdb().lookup_procedure('plug-in-plasma')
    pdb_config = pdb_proc.create_config()
    pdb_config.set_property('run-mode', Gimp.RunMode.NONINTERACTIVE)
    pdb_config.set_property('image', image)
    pdb_config.set_property('drawable', mask)
    pdb_config.set_property('seed', int(time.time()))
    pdb_config.set_property('turbulence', turbulence)
    pdb_proc.run(pdb_config)



RE: Selecting one pixel from each blob in a binary image - cam92473 - 10-27-2024

Hi,

Thanks all for your help. I tried incorporating the dilation idea into a script, but although ingenious, it ended up being too slow for my application. I ended up using the following method: select by color (white), convert the selections to paths, find the mean of the control points for each path, and use the fuzzy selection tool on each of those mean points with a lenient sample threshold to get the correct blobs. Luckily this isn't too slow, especially since I do some steps beforehand to ensure the number of white selections isn't too large (I only really need the larger blobs).

I can certainly attest to the fact that Gimp 3 code is more verbose than Gimp 2 code, as I am incorporating this script into a larger algorithm (written in Gimp 3 python fu), which currently stands at 2000 lines long!


RE: Selecting one pixel from each blob in a binary image - Ofnuts - 10-27-2024

(10-27-2024, 02:46 PM)cam92473 Wrote: .... as I am incorporating this script into a larger algorithm (written in Gimp 3 python fu), which currently stands at 2000 lines long!

You know that of course they are libraries for image processing in Python directly, for instance Pillow and openCV, so you could be reinventing the wheel here (plus the core of these libs is actually written in C, so they are quite fast).


RE: Selecting one pixel from each blob in a binary image - cam92473 - 10-27-2024

(10-27-2024, 05:47 PM)Ofnuts Wrote:
(10-27-2024, 02:46 PM)cam92473 Wrote: .... as I am incorporating this script into a larger algorithm (written in Gimp 3 python fu), which currently stands at 2000 lines long!

You know that of course they are libraries for image processing in Python directly, for instance Pillow and openCV, so you could be reinventing the wheel here (plus the core of these libs is actually written in C, so they are quite fast).

Yes, it all began when I was trying to find a way to apply a circular median kernal to my image data. I found out that Gimp's circular median blur was faster than those in Python image processing libraries (even with the high-precision switch turned on), and so I incorporated it into my pipeline. I then began adding more pieces to my python-fu script and turning it into a full-fledged image processing algorithm. I also enjoy getting ideas from the Gimp user interface, on what further transformations I can incorporate into my algorithm, so in that sense it has been very helpful (although trying to code in Gimp 3.0 has been challenging at times, especially given how buggy it can be).