# How to group contours in close proximity to each other?

**URL:** <https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719>\
**Category:** Python\
**Created:** [February 23, 2021, 3:41am UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719 "2021-02-23T03:41:38Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![boydaloidus](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@boydaloidus](https://forum.opencv.org/u/boydaloidus)\
**Post date:** [February 23, 2021, 3:41am UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/1 "2021-02-23T03:41:38Z")

</div>

Hi all, first time on here.

As per the attached diagram, I’m trying to use openCV commands to group together all proximal blobs in an image, box them with a minimal rectangle and return size of the largest group of blobs (minimal rectangle) and the coordinates of its X and Y position on the screen. Origin is at top left. Ideally, it would also return order of size; largest to smallest, of all blob groups and their respective X and Y centroid coordinates.

Any assistance much appreciated.

 ![diagram to try to find soln to group blobs - opencv forum](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/e/e74e5ec13af02bd41b2e6e806c2b2d234e22375d.jpeg)

---

<div class="post-metadata">

**Author:** ![laurent.berger](https://avatars.discourse-cdn.com/v4/letter/l/ec9cab/32.png) [@laurent.berger](https://forum.opencv.org/u/laurent.berger)\
**Post date:** [February 23, 2021, 8:22am UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/2 "2021-02-23T08:22:10Z")

</div>

Hi,  
There is no really answer to your question, except Brute Force method.  
Some methods give you an approach answer. Have a look in [clustering module](https://docs.opencv.org/master/dc/de5/group__flann.html) and [machine learning module](https://docs.opencv.org/master/dd/ded/group__ml.html) and [kmeans](https://docs.opencv.org/master/d5/d38/group __core__ cluster.html#ga9a34dc06c6ec9460e90860f15bcd2f88)

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [February 23, 2021, 10:51am UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/3 "2021-02-23T10:51:20Z")

</div>

clustering is right. `flann` might be useful in this situation. I disagree with k-means, since there is no `k` here.

maybe you want to use _mean shift_.

> **[Mean shift](https://en.wikipedia.org/wiki/Mean_shift)**
>
> Mean shift is a non-parametric feature-space analysis technique for locating the maxima of a density function, a so-called mode-seeking algorithm. Application domains include cluster analysis in computer vision and image processing.
> The mean shift procedure was originally presented in 1975 by Fukunaga and Hostetler.
> Mean shift is a procedure for locating the maxima—the modes—of a density function given discrete data sampled from that function. This is an iterative method, and we start with an i...

---

<div class="post-metadata">

**Author:** ![boydaloidus](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@boydaloidus](https://forum.opencv.org/u/boydaloidus)\
**Post date:** [February 23, 2021, 10:58am UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/4 "2021-02-23T10:58:40Z")

</div>

Thanks for that Laurent! I wonder whether it might be worth blurring the image in order to make the clustered groups of contours appear as one contour - do you think that might be worth trying as a simpler approach and which commands would you suggest? I have used cv2.medianblur but can’t seem to get enough blurriness in the result. cheers.

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [February 23, 2021, 11:00am UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/5 "2021-02-23T11:00:44Z")

</div>

if you want a simple approach, do a “morphological closing” with an appropriate kernel and number of iterations.

_do not_ blur. wrong operation here.

---

<div class="post-metadata">

**Author:** ![boydaloidus](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@boydaloidus](https://forum.opencv.org/u/boydaloidus)\
**Post date:** [February 23, 2021, 11:33pm UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/6 "2021-02-23T23:33:01Z")

</div>

I like the sound of that crackwitz (great name by the way). simple approach is best here with this, as it does not have to be super accurate at this stage. I’ll have a play and see if this solves it, so many thanks. Interested to know why some sort of blur wouldn’t work on this? cheers.

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [February 23, 2021, 11:57pm UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/7 "2021-02-23T23:57:24Z")

</div>

I don’t see how a blur would help anything at all, but it might hurt the situation.

that’s the case for most things one _could_ do (such as, make a cup of tea, or walk around a tree seven times). they simply don’t make sense to do. and it is hard to explain _why_ those things don’t make sense… because they don’t make sense, there are no arguments to be made.

anything a blur _might_ somehow accomplish, _if_ followed by the right operations, is done better with other operations that actually move you towards the solution.

basically, I consider the suggestion to be unfounded. it is tedious to argue _against_ something that hasn’t been argued _for_.

> [@boydaloidus](#):
>
> make the clustered groups of contours appear as one contour

morphological closing does that. morph. ops aren’t blurs though. a blur doesn’t _quite_ do that, and not even completely. and a _median_ blur doesn’t even remotely do what you want.

I lack the words to express how much I want to dissuade you from continuing this line of thought.

I just realized, you posted a sketch of your real situation. you should always try to present real data or come close to it.

morph ops work on grayscale data and binary data (just black and white). that’s different from the illustration which just has (unfilled) circles.

---

<div class="post-metadata">

**Author:** ![boydaloidus](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@boydaloidus](https://forum.opencv.org/u/boydaloidus)\
**Post date:** [February 24, 2021, 1:46am UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/8 "2021-02-24T01:46:26Z")

</div>

That’s fine, I’ll follow up on the morph ops. The only thing is that the closing morph seems to require the shapes to be in the same bound shape in order to close on them. Now that I look back at my attached image, I should have included a before and after ops image to make it clearer. As you’ll see in the attached, I actually start with a collection of separate blobs which are in close proximity to each other. The red dotted line is the red minimum rectangle which is done by the processing, as well as the centroid. From this, am I right in assuming that the morph would not work on this problem?  
start with this image…

 ![diagram to try to find soln to group blobs - opencv forum 1](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/f/f6be8593a9d9d0f852a30efdf164705a6fb5e109.jpeg)  
process to get this image. ie. with centroids of clustered blobs ordered by size, to get the original image i posted.

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [February 24, 2021, 3:36pm UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/9 "2021-02-24T15:36:50Z")

</div>

I don’t understand what you’re asking. “bound shape” doesn’t mean anything.

do you have a raster image of blobs, or do you have centroids and covariances?

---

<div class="post-metadata">

**Author:** ![boydaloidus](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@boydaloidus](https://forum.opencv.org/u/boydaloidus)\
**Post date:** [February 24, 2021, 10:00pm UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/10 "2021-02-24T22:00:11Z")

</div>

The best way I can explain it was by putting in the second image, attached to my reply to you. I actually found something that I think will work on it which you might find interesting. Here’s the link. [https://dsp.stackexchange.com/questions/2564/opencv-c-connect-nearby-contours-based-on-distance-between-them](https://dsp.stackexchange.com/questions/2564/opencv-c-connect-nearby-contours-based-on-distance-between-them)

I’m using the first answer with the two code options in it. Haven’t got it working yet but it seems to be the way to go, unless there are commands out there that will do the job more rapidly, as this seems a bit slow from what I’ve read in that post.

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [February 24, 2021, 10:54pm UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/11 "2021-02-24T22:54:46Z")

</div>

I’m not asking for clarification, I’m asking for real data instead of the illustration. your illustration uses ellipses. real data would look like the questioner’s picture on the stack overflow question.

please don’t. that first answer uses explicit loops. that’s a good indication that the solution is inefficient, if not outright wrong. besides, you must have had a picture before you can have contours. it makes absolutely NO sense to calculate contours and then incur O(n^2) cost due to a silly approach from someone on Stack Overflow

how about simply running a morphological closing? the _second_ answer proposes exactly that.

please post actual sample data so I can demonstrate this to you.

---

<div class="post-metadata">

**Author:** ![boydaloidus](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@boydaloidus](https://forum.opencv.org/u/boydaloidus)\
**Post date:** [February 25, 2021, 12:54am UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/12 "2021-02-25T00:54:24Z")

</div>

Here’s an example binary image of the type of thing I’m looking for, so this is what the cv2.findcontours command uses as input.

 ![7 thresh](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/6/6151592e79670466097cfa6252b67768a7b4f4fd.jpeg)

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [February 25, 2021, 7:05am UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/13 "2021-02-25T07:05:47Z")

</div>

this is a 9x9 kernel and 16 iterations. I think you see where this goes.

 ![6151592e79670466097cfa6252b67768a7b4f4fd_morph_close](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/a/a5dd4d4d01d9a67726c150528a29f1ea7c759dc9.jpeg)

---

<div class="post-metadata">

**Author:** ![boydaloidus](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@boydaloidus](https://forum.opencv.org/u/boydaloidus)\
**Post date:** [February 26, 2021, 1:41am UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/14 "2021-02-26T01:41:27Z")

</div>

Exackery Crackwitz! apologies for misunderstanding the use of dilution but I too tried it yesterday and indeed it did a pretty good job! I assume that the kernel size represents effectively the ‘paint brush size’ and the iterations, how many times you need to go around with that paint brush size to fill the area out…only an analogy but you get what i mean. is that about right? also, i assume if you use the same parameters of kernel and iterations then you can erode the diluted shapes back to the original size of the blob grouped mass? cheers.

---

<div class="post-metadata">

**Author:** ![boydaloidus](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@boydaloidus](https://forum.opencv.org/u/boydaloidus)\
**Post date:** [March 19, 2021, 12:18am UTC](https://forum.opencv.org/t/how-to-group-contours-in-close-proximity-to-each-other/1719/15 "2021-03-19T00:18:39Z")

</div>

Many belated thanks for all your help on this Senor Crackwitz!! The dilution command worked extremely well!
