'How to connect broken lines that cannot be connected by erosion and dilation?
I have an image like this that has multiple stoppers and some of the lines are broken. To connect this broken line, I used a morphological operation like this:
import cv2
import numpy as np
img = cv2.imread('sample.png', cv2.IMREAD_GRAYSCALE)
morph = cv2.morphologyEx(im, cv2.MORPH_CLOSE, np.ones((10,10),np.uint8))
But this didn't connect my broken lines. How can I connect the lines without affecting the other lines?
img
A line break is a break between two small lines in the center of the image. Only the discontinuous part does not have rounded ends.
applied morphological operation
Solution 1:[1]
-
- You can use
createFastLineDetector
for detecting each line.
- You can use
-
- Calculate the slope of the current and neighboring lines.
-
- If the slope of current and neighboring lines are the same draw line.
Initializing Line Detector
We will be using ximgproc
library for detecting lines.
import cv2
img = cv2.imread("lines.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
d = cv2.ximgproc.createFastLineDetector()
lines = d.detect(gray)
- The
lines
variable returns similar values like[[14.82, 78.90, 90.89, 120.78]]
wherex1=14.82
,y1=78.90
,x2=90.89
,y2=120.78
respectively.
Calculating Slope
The slope of a line is calculated with the formula: m = (
y2
-y1
) / (x2
-x1
)For a given line object, get the coordinates and return the slope.
-
def calculate_slope(line_object): x_point1 = line_object[0] y_point1 = line_object[1] x_point2 = line_object[2] y_point2 = line_object[3] m = abs((y_point2 - y_point1) / (x_point2 - x_point1)) m = float("{:.2f}".format(m)) return m
Comparing Slopes
-
- Check the equality of the lines. if the points are equal, that means they are the same line.
-
for current_line in lines: current_slope = calculate_slope(current_line[0]) for neighbor_line in lines: current_x1 = int(current_line[0][0]) current_y1 = int(current_line[0][1]) current_x2 = int(current_line[0][2]) current_y2 = int(current_line[0][3]) compare_lines = current_line == neighbor_line[0] equal_arrays = compare_lines.all()
-
- If the lines are not equal, calculate the neighbor's line slope.
if not equal_arrays: neighbor_slope = calculate_slope(neighbor_line[0])
- If the lines are not equal, calculate the neighbor's line slope.
-
- If slopes are equal, draw the line. From
neighbor
tocurrent
andcurrent
toneighbor
.if abs(current_slope - neighbor_slope) < 1e-3: neighbor_x1 = int(neighbor_line[0][0]) neighbor_y1 = int(neighbor_line[0][1]) neighbor_x2 = int(neighbor_line[0][2]) neighbor_y2 = int(neighbor_line[0][3]) cv2.line(img, pt1=(neighbor_x1, neighbor_y1), pt2=(current_x2, current_y2), color=(255, 255, 255), thickness=3) cv2.line(img, pt1=(current_x1, current_y1), pt2=(neighbor_x2, neighbor_y2), color=(255, 255, 255), thickness=3)
- If slopes are equal, draw the line. From
Result
Possible Question But why couldn't you connect the following parts?
Answer
Well, the red dotted line slopes are not equal. Therefore I couldn't connect them.
Possible Question Why didn't you use dilate
and erode
methods? as shown in here
Answer
I tried, but the result is not satisfactory.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |