如何在图像中找到桥状结构的端点?
以下是一般概念。
我有一组看起来像你在左栏上看到的图像,如上图所示。我想要检测/定位的实际上是上图中右侧列显示的两个端点。这就像找到“桥梁”的“两端点”一样。
我已经应用了一些基本的形态学操作;但是,要么我做错了,要么那些基本的形态学操作在这种情况下不起作用。 (我已经尝试将它变成骷髅;但是,一旦形成骷髅,我似乎无法检测到有三条边的十字架)。
感谢您之前的建议;然而,看起来原始的图像集不能像我之前绘制的那样完全概括。
我已附上此问题的最新更新。下面是更详细的表示,其包括原始分割区域和经历“变薄”形态学操作的相应图像。同样,左侧是最初分割的区域;而在右边则是要检测的点。
答案 0 :(得分:7)
使用Python,NumPy,Pymorph和Mahotas:
的解决方案import pymorph as m
import mahotas
from numpy import where, reshape
image = mahotas.imread('input.png') # Load image
b1 = image[:,:,0] < 100 # Make a binary image from the thresholded red channel
b2 = m.erode(b1, m.sedisk(4)) # Erode to enhance contrast of the bridge
b3 = m.open(b2,m.sedisk(4)) # Remove the bridge
b4 = b2-b3 # Bridge plus small noise
b5 = m.areaopen(b4,1000) # Remove small areas leaving only a thinned bridge
b6 = m.dilate(b3)*b5 # Extend the non-bridge area slightly and get intersection with the bridge.
#b6 is image of end of bridge, now find single points
b7 = m.thin(b6, m.endpoints('homotopic')) # Narrow regions to single points.
labelled = m.label(b7) # Label endpoints.
x1, y1 = reshape(where(labelled == 1),(1,2))[0]
x2, y2 = reshape(where(labelled == 2),(1,2))[0]
outputimage = m.overlay(b1, m.dilate(b7,m.sedisk(5)))
mahotas.imsave('output.png', outputimage)
答案 1 :(得分:5)
以下是在对图像进行骨架化后定位分支点的代码示例:
import pymorph as m
import mahotas
from numpy import array
image = mahotas.imread('1.png') # load image
b1 = image[:,:,1] < 150 # make binary image from thresholded green channel
b2 = m.thin(b1) # create skeleton
b3 = m.thin(b2, m.endpoints('homotopic'), 15) # prune small branches, may need tuning
# structuring elements to search for 3-connected pixels
seA1 = array([[False, True, False],
[False, True, False],
[ True, False, True]], dtype=bool)
seB1 = array([[False, False, False],
[ True, False, True],
[False, True, False]], dtype=bool)
seA2 = array([[False, True, False],
[ True, True, True],
[False, False, False]], dtype=bool)
seB2 = array([[ True, False, True],
[False, False, False],
[False, True, False]], dtype=bool)
# hit or miss templates from these SEs
hmt1 = m.se2hmt(seA1, seB1)
hmt2 = m.se2hmt(seA2, seB2)
# locate 3-connected regions
b4 = m.union(m.supcanon(b3, hmt1), m.supcanon(b3, hmt2))
# dilate to merge nearby hits
b5 = m.dilate(b4, m.sedisk(10))
# locate centroids
b6 = m.blob(m.label(b5), 'centroid')
outputimage = m.overlay(b1, m.dilate(b6,m.sedisk(5)))
mahotas.imsave('output.png', outputimage)
答案 2 :(得分:2)
这里有Mathematica中的代码示例,可能不是最佳的:
f[i_] :=
Module[{t, i2, w, z, neighbours, i3, cRed},
(t = Thinning[ColorNegate@i, 15];
i2 = ImageData@Binarize[ DeleteSmallComponents[
ImageSubtract[t, Dilation[Erosion[t, 1], 1]], 100], .1];
For[w = 2, w < Dimensions[i2][[1]], w++,
For[z = 2, z < Dimensions[i2][[2]], z++,
If[i2[[w, z]] == 1 && i2[[w + 1, z + 1]] == 1,
i2[[w, z + 1]] = i2[[w + 1, z]] = 0];
If[i2[[w, z]] == i2[[w - 1, z - 1]] == 1,
i2[[w, z - 1]] = i2[[w - 1, z]] = 0];
If[i2[[w, z]] == i2[[w + 1, z - 1]] == 1,
i2[[w, z - 1]] = i2[[w + 1, z]] = 0];
If[i2[[w, z]] == i2[[w - 1, z + 1]] == 1,
i2[[w, z + 1]] = i2[[w - 1, z]] = 0];
]
];
neighbours[l_, k_, j_] :=
l[[k - 1, j]] + l[[k + 1, j]] + l[[k, j + 1]] + l[[k, j - 1]] +
l[[k + 1, j + 1]] + l[[k + 1, j - 1]] + l[[k - 1, j + 1]] +
l[[k - 1, j - 1]];
i3 = Table[
If[i2[[w, z]] ==1,neighbours[i2, w, z], 0],{w,2,Dimensions[i2][[1]]-1},
{z,2,Dimensions[i2][[2]]-1}];
cRed =
ColorNegate@Rasterize[Graphics[{Red, Disk[]}], ImageSize -> 15];
ImageCompose[
ImageCompose[i,
cRed, {#[[2]], Dimensions[i2][[1]] - #[[1]]} &@
Position[i3, 1][[1]]],
cRed, {#[[2]], Dimensions[i2][[1]] - #[[1]]} &@
Position[i3, 1][[2]]])];
答案 3 :(得分:1)
我想到了一种通用的方法:
1)跟踪轮廓并将其转换为路径。因此,有一条路径遍布整个形状,它由线段组成
2)寻找干线 - 路径上的线段大致平行一段距离的位置(空间索引,例如八叉树或kdtree将有助于保持搜索本地化)
3)沿着某个方向走路,直到双方突然发散。这是干的终点4)按照另一个方向的路径找到另一个端点
答案 4 :(得分:0)
您还可以尝试在图像上运行一个移动窗口,其中的滤镜是内部像素值的总和。调整大小以表示桥宽度的两倍。当你从桥上跑到岸边时,你应该会看到一个相当急剧的过渡。
答案 5 :(得分:0)
找到的一个有趣的特征是骨架中的连接点,它与对象相关对象的补充的距离函数值最小。
X - 输入图像中设置为黑色的对象 D(X) - 物体X的距离函数 D(~X) - 对象补码的距离函数 - 这通常类似于自身设置的对象的骨架化。
因此,这里的基本直觉是物体X的拓扑结构使得在重头附近可以找到夹点 - 一个你肯定在骨架中有一个连接点的地方 - 同时也是一个低值的对象补充的距离函数。颈部或夹点在接合点处产生最小值。
也许这个想法需要一些调整 - 但我猜一个人可以解决。