ahbutfore
ahbutfore

Reputation: 399

Connected line detection with opencv

I'm trying to convert an image that looks like:

enter image description here

Into one that looks something like (I drew this):

enter image description here

I want to detect and draw lines in the image where the thick/thin sections are smoothed out to create a somewhat even width and where the lines are overlapping if the pixels in the image are touching. (if you zoom in on the original image you can see even the thin segments do have pixels connecting them)

The two problems I'm running into are:

  1. Thin sections of pixels in the original image end up broken up. So the pixels of the transformed image are not overlapping where they are in the original, thus creating gaps in the lines.
  2. Some of the lines are close enough together, that if I dilate things to try and fix #1, the detected lines end up overlapping each other where they shouldn't.

I'm currently trying to mess with Canny/Hough to get this working, but thus far have been unsuccessful.

edges = cv2.Canny(img, 50, 200, None, 3)

hough_img = np.copy(img) * 0  # creating a blank to draw lines on
lines = cv2.HoughLinesP(img, rho=1, theta=np.pi / 180, threshold=35, lines=np.array([]),
                        minLineLength=3, maxLineGap=2)
for line in lines:
    for x1, y1, x2, y2 in line:
        cv2.line(hough_img, (x1, y1), (x2, y2), (255, 0, 0), 2)

enter image description here

Upvotes: 2

Views: 2040

Answers (1)

Mark Setchell
Mark Setchell

Reputation: 207808

Maybe scikit-image medial_axis() is what you need:

from skimage.io import imread
from skimage.morphology import medial_axis

# Load image
im = imread('https://i.sstatic.net/cqgfc.png',as_gray=True)
skel= medial_axis(im)

enter image description here


Or, as kindly suggested by Bart in the comments, you can use skeletonize():

from skimage.io import imread, imsave
from skimage.morphology import skeletonize
from skimage.filters import threshold_otsu

# Load image
im = imread('https://i.sstatic.net/cqgfc.png',as_gray=True)

# Get Otsu threshold
t = threshold_otsu(im)

# Binarize and skeletonize
r = skeletonize(im>threshold_otsu(im))*255

# Save
imsave('result.png',r)

enter image description here

Upvotes: 6

Related Questions