Reputation: 306
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.
Upvotes: 3
Views: 4913
Reputation: 1885
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
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)
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 shown. Lowering the parameters
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.
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()
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.
Upvotes: 6