Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find Line in skeleton Images OpenCV python

I have the following picture:

and I want to find the lines to do some calculations, average length etc ... I tried to use HoughLinesP, but it doesn't find the lines. How can I do?

This is my code:

sk=skeleton(mask);
rows, cols = sk.shape
imgOut=np.zeros((rows,cols,3),np.uint8)
imgOut[:,:,0]=0
imgOut[:,:,1]=0
imgOut[:,:,2]=0


minLineLength = 0
maxLineGap = 0

lines = cv2.HoughLinesP(sk,1,np.pi/180,100,minLineLength,maxLineGap)
for x1,y1,x2,y2 in lines[0]:
    cv2.line(imgOut,(x1,y1),(x2,y2),(0,255,0),2)

print len(lines[0])

cv2.imshow('skel',sk)
cv2.imshow('Line',imgOut)
cv2.imwrite('Out.bmp',imgOut)

Output:

If i change the parameters of HoughLinesP I only get fragments of line, not a solid line.

like image 938
Mex Avatar asked Sep 01 '26 22:09

Mex


1 Answers

Although the Hough lines algorithm is meant for lines only (and you're clearly dealing with curves), there might be a way to salvage your attempt, by greatly augmenting the rho and theta parameters.

This should make the curved sides point to the same bin rather than be split in different bins.


EDIT : You have a bit of a problem : OpenCV's definition of cv2.HoughLinesP. From the documentation :

cv2.HoughLinesP(image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]])

As you might see, the 5th parameter is lines, the output variable. Your call is

cv2.HoughLinesP(sk,1,np.pi/180,100,minLineLength,maxLineGap)
                                   ^^^^^^^^^^^^^
                                   lines         

So your given minLineLength parameter has no effect (it becomes an output variable), and maxLineGap has wrong interpretation too.

I suggest to explicitly write parameter names (without parameter tweaks yet)

cv2.HoughLinesP(sk.astype(np.uint8),rho=1,theta=np.pi/180,threshold=100,
                minLineLength=minLineLength,maxLineGap=maxLineGap)

a bit long to write, but at least OpenCV doesn't mix the parameters anymore

Visualizing the lines

I changed the line color for each line for an easier time visualizing which segment is where :

    color = np.random.uniform(0,255,3)
    cv2.line(imgOut,(x1,y1),(x2,y2),color,2)

Changing parameters

By having less bins for rho and theta (achieved by increasing the parameters) you will have more chances of having the edges of a curve vote for the same line-bin.

Here are some attempts (full code below)

rho=5,theta=np.deg2rad(10),threshold=10,minLineLength=5,maxLineGap=2

Too many lines Too many lines shown. Lowering the parameters

Why skeletonize ?

Your input image (as given) looks like edges are already there. The output of skeletonize is only the central line of edges, which sounds like a positive thing, but for Hough Lines, it means reducing the number of pixels "voting" for line segments.

# sk = skeletonize(mask==255)
sk = mask==255

This didn't change much in specifics, but I thought it couldn't hurt the task at hand.

Why not label ?

What you're trying to get is individual line segments. Why not just label the image ?

from matplotlib import pyplot as plt
from scipy import ndimage 

labels,nblabels = ndimage.label(sk)
plt.imshow(labels,'jet')
plt.show()

Labelled image

By applying a little morphological operators you will get individual lines or in the worst case, line branchings.

Now you can select the lines individually by doing

line = labels == 2 # select the pixels with label 2 only

Applying Hough lines to these might be overkill to untangle them, but you'd have significantly broken down your problems already.

Calculation of metrics is now super easy (see ndimage.measurement documentation) and iteration over arrays is super simple.

like image 183
Jiby Avatar answered Sep 03 '26 14:09

Jiby



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!