How to connect broken lines in a binary image using Python/Opencv
Asked Answered
S

3

17

How can I make these lines connect at the target points? The image is a result of a skeletonization process.

Resulting Image From Skeletonization

Points That I Need To Connect

I'm trying to segment each line as a region using Watershed Transform.

Sibilate answered 9/5, 2017 at 1:48 Comment(1)
To connect broken lines/edges based on contour extremities have a look at this #71811885Tildi
B
21

MikeE's answer is quite good: using dilation and erosion morphological operations can help a lot in this context.
I want to suggest a little improvement, taking advantage of the specific structure of the image at hand. Instead of using dilation/erosion with a general kernel, I suggest using a horizontal kernel that will connect the endpoints of the horizontal lines, but will not connect adjacent lines to one another.

Here's a sketch of code (assuming the input image is stored in bw numpy 2D array):

import cv2, numpy as np

kernel = np.ones((1,20), np.uint8)  # note this is a horizontal kernel
d_im = cv2.dilate(bw, kernel, iterations=1)
e_im = cv2.erode(d_im, kernel, iterations=1) 

What you get is the dilated image:
enter image description here

Note how the gaps are closed, while maintaining the distinct horizontal lines

And the eroded image:
enter image description here

To remove artifacts created by dilate/erode, I suggest to extract the skeleton again.
If you further apply skeleton morphological operation to the eroded image you can get this result:
enter image description here

Once you have the curves connected you do not need to use watershed segmentation, but rather use connected components to label each curve.

Bibb answered 9/5, 2017 at 7:14 Comment(1)
Thank you so much, Shai!Sibilate
D
5

Since the image is already monochromatic, you can use morphological transformations to close broken lines.

In case you need an example, you can find it in the documentation here: http://docs.opencv.org/2.4/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html#closing

It works by first dilating the white areas in the image and then eroding back by the same amount. Effectively closing any holes in the white areas. More details and examples can be found here: http://docs.opencv.org/2.4/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html

This strategy requires that the gap in the broken line is smaller than the distance between neighboring lines.

It will not work, if the lines cross, or if the lines are too close to each other. However I think it will work quite nicely in your example.

You can also remove the artifacts below the third line using the erode function.

Djambi answered 9/5, 2017 at 6:47 Comment(1)
How much time do you have for the computation?Djambi
C
1

I am working on similar problem but it is more complex and at some spots lines are very near so morphological transformations end up merging them. If someone know of any other way please suggest. Thanks in advance!

Coming to your problem. I think you don't even need morphological operations. As you have already skeletonized the image you can simply design a kernel to detect the points where lines break and join those points using distance and slope(derivative) as a criteria. I don't know if it will work 100% but you may give it a try.

Convertible answered 20/1, 2020 at 8:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.