在骨架图像OpenCV python中查找线

Mex*_*Mex 3 python opencv image-processing

我有以下图片:

我想找到一些线来做一些计算,平均长度等...我试图使用HoughLinesP,但它找不到线条.我能怎么做?

这是我的代码:

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)
Run Code Online (Sandbox Code Playgroud)

输出:

如果我更改HoughLinesPI 的参数只获得行的片段,而不是实线.

Jib*_*iby 5

尽管霍夫线算法仅用于线条(并且您明确处理曲线),但可能有一种方法可以通过大大增加rhotheta参数来挽救您的尝试.

这应该使弯曲的侧面指向相同的箱子而不是在不同的箱子中分开.


编辑:你有一个问题:OpenCV的定义cv2.HoughLinesP.从文档:

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

如您所见,第五个参数是lines输出变量.你的电话是

cv2.HoughLinesP(sk,1,np.pi/180,100,minLineLength,maxLineGap)
                                   ^^^^^^^^^^^^^
                                   lines         
Run Code Online (Sandbox Code Playgroud)

所以你的给定minLineLength参数没有效果(它变成输出变量),并且maxLineGap也有错误的解释.

我建议显式写参数名称(还没有参数调整)

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

写入有点长,但至少OpenCV不再混合参数

可视化线条

我更改了每一行的线条颜色,以便更容易地查看哪个线段在哪里:

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

改变参数

通过具有较少的垃圾箱rhotheta(通过增加参数来实现),那么必须具有针对同一线路斌的曲线投票边缘的更多的机会.

以下是一些尝试(完整代码如下)

rho=5,theta=np.deg2rad(10),threshold=10,minLineLength=5,maxLineGap=2
Run Code Online (Sandbox Code Playgroud)

线太多了 显示的线太多.降低参数

为什么要骨化?

您的输入图像(如给定的)看起来像边缘已经存在.的输出skeletonize是仅边缘的中心线上,这听起来像一个积极的事情,但对于霍夫线,这意味着减少像素"投票"为线段的数目.

# sk = skeletonize(mask==255)
sk = mask==255
Run Code Online (Sandbox Code Playgroud)

这在具体细节上没有太大变化,但我认为它不会伤害手头的任务.

为什么不贴标签?

你想要得到的是单独的线段.为什么不标记图像?

from matplotlib import pyplot as plt
from scipy import ndimage 

labels,nblabels = ndimage.label(sk)
plt.imshow(labels,'jet')
plt.show()
Run Code Online (Sandbox Code Playgroud)

标记图像

通过应用一些形态学运算符,您将得到单独的行或在最坏的情况下,行分支.

现在,您可以单独选择行

line = labels == 2 # select the pixels with label 2 only
Run Code Online (Sandbox Code Playgroud)

将霍夫线应用于这些可能是过度的解开它们,但你已经明显地解决了你的问题.

度量的计算现在非常简单(参见ndimage.measurement文档),并且对数组的迭代非常简单.