Best method for Image Processing for Contour Extraction

I am working on a project that involves image processing for contour extraction and I’m seeking some guidance on the best approach. I have a basic understanding of Python, but I am open to solutions in C# as well, especially if they offer increased efficiency or ease of integration.

Objective: My goal is to process bitmap images to group adjacent pixels by color, and then output the outline of each clustered pixel group as a crv/polyline along with the related color value. These dimensions of these images wil be quite large, more towards the 4k to 8k resolution, with lost of fine details. For now I assume a high contrast image using black&white, but I assume that for the code method it should not make a difference what specific colors the source img has and how many distinct colors , maybe a filter to find specif color groups might be even usefull/faster

Current Approach: using some Python code that uses libraries like Numpy, and OpenCV. To finds contours for each unique value in the image, and then export these contours as crvs. Here is the sample code https://trinket.io/python3/8bb5b78429
trinket_plot (1)

But this required GH2 to work, so if an equivalent and fast method exists for GH1, i’'d definetly want to hear about it. I’m am perfectly ok, to use an external plugin if that does the job.

Previous Attempts: I have tried using the Trace Bitmap node such as provided by the Bitmap Plus plugin, but found that it doesn’t achieve the level of precision I am looking for

Exploring RTree: I am also considering the use of RTree for fast calculations of distances between pixel coordinates. Specifically, the RTree Closest Point component could potentially be employed to efficiently identify and group pixels based on spatial proximity, forming a basis for further color-based clustering (k-means ?). Any insights or experiences with such an approach would be greatly appreciated.

Exploring Mesh: Maybe make a mesh by the list of colors and maybe do something smart … stillno sure what :wink:

Hello
have you seen this discussion ?

Hi @laurent_delrieu yes, i remember reading it, i just forgot all about how related it is to my request. I’ll dive right into it. Thanks!!

RTrees are not the way to go.

Assuming that you know how to Cluster things (let’s forget // for the monent)
:

  1. Using some proper Class (in order to monitor the x/y cell value) Cluster your pixels. This yields a higher order collection (Tree) or … use suitable Properties in the Class to control the collections “within” the Class.
  2. Each pixel has a center and 4 corners (monitor these using some Property as well).
  3. So given some Cluster (i.e. a GroupBy pixel value result) order items (in x/y), separate islands (i.e. singular contacts) and then do a doule Loop and “trace” the outlines - so to speak.

Level required: mid to advanced. I have some C# that does that but is written a million years ago and I’m not sure where it is.

Or you can start using a Matrix (and cell vals representing Colors). If you want to visualize the Matrix remember that R/C 0,0 pos is the upper left corner.

BTW: Tons of related stuff around. Like:

BTW: did a quick search - but I’m not in the practice right now: the only C# found is something that given Voxels … yields a closed Mesh from the “outer” faces … meaning that somehow this is the 3d take of your 2d puzzle (kinda).

interesting links, good to know what terms to google for. I try to make a fast and scaleable script based upon both your inputs and share the results (optimistically i am aiming for 8k res processing in < 5 sec calculation)

Another - stupid/lazy- way could be: sample your pixels (as meshes) into the Class collection then GroupBy(x=>x.Color), then OrderBy(x=>x.Center.X).ThenBy(x=>x.Center.Y) and Append’m into a Mesh (per Group). Then just use the SplitDisjointPieces Method and then the GetNakedEdges Method per island (i.e. a Polyline where edges are connected with one Face).

But this is indeed kinda flying from DC to NY via LA. In fact is so stupid that I’m tempted to write another C# that is - more or less - the art of pointless.

However … give it a spin (Mesh ops [blame floats] are fast). And your Elapsed target (5000 milliseconds) is rather generous (hideous to me if you ask). All that prior implenenting some // approach (hope dies last).

Update: finish the attached (is pointless but then what isn’t?)

Mesh_BoundariesByColor_V1.gh (11.4 KB)

thanks Peter, :+1:

OK … stupid things are like Cuban cigars: the more the better.

So I did the right (i.e. the wrong) thing. Result? 100 ms VS 7K pixels as Meshes (using an ancient i5 - I always use a crap CPU when writing code). So expect 20 ms max (using ~10+K pixels) on an 14th gen I9 … plus a thread safe // approach.



Challenge(s) for you:

  1. Define the Class (and rnd test Meshes/Colors) in one C# - the first as captured above.
  2. Unbox (*) the Class content (as List of Type object) in a 2nd C# and then do the boundaries as explained above.

(*) notify if you don’t know how to do that.

I hear you: Is this your best shot? No it’s the worst … but who cares?

3 Likes

wow, that sure looks like a flawless victory to me. Impressive, and inspiring. You’d be surprised how often the stupid thing is the right thing

Get the part related with reading a Class defined in one C# i.e. unboxing it in another C#. Always do that for more than obvious reasons.

Input the Class content as a List of type object, define a Class with exactly the same Properties (as the OEM) and then do:

So as a challenge try to put’m all together and … if you’ll hit the wall … notify (the full thing is waiting for you).

Added a 3rd C# that does the viz part: