5

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.

image

applied morphological operation

applied morphological operation

Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
methemet
  • 53
  • 4
  • 1
    You likely want to detect the lines (maybe Hough?) and find some logic that will determine whether to connect the lines or not. You could also make a skeleton, detect end points, then try to figure out which end points to join. A simple closing is never going to give you good results here. – Cris Luengo Sep 03 '20 at 16:32
  • To connect curved, broken lines/edges based on contour extremities have a look at this https://stackoverflow.com/questions/71811385/connecting-disjointed-lines-or-edges-in-binary-images/71816288#71816288 – Jeru Luke Apr 23 '22 at 15:36

1 Answers1

5
    1. You can use createFastLineDetector for detecting each line.

    1. Calculate the slope of the current and neighboring lines.

    1. 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]] where x1=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


    1. 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()
      
    1. If the lines are not equal, calculate the neighbor's line slope.
      if not equal_arrays:
          neighbor_slope = calculate_slope(neighbor_line[0])
      
    1. If slopes are equal, draw the line. From neighbor to current and current to neighbor.
      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)
      

Result


enter image description here

Possible Question But why couldn't you connect the following parts?

enter image description here

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.

Ahmet
  • 7,527
  • 3
  • 23
  • 47
  • 2
    Nice answer! Only the part where you do `current_slope == neighbor_slope` makes me worry. I've learned to never, ever, do an equality comparison with floating-point numbers. Add a small tolerance to the comparison: `abs(current_slope - neighbor_slope) < 1e-3` (or similar). – Cris Luengo Sep 03 '20 at 20:27
  • This is the first time, I have a compliment from my senior. Thanks for evaluating my answer. I've added the change as you suggested. I appreciate your comment. – Ahmet Sep 03 '20 at 20:32
  • Sorry for the late reply, that's a very good idea! Thank you for your reference. – methemet Sep 17 '20 at 22:55