Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中的命中或未命中形态学在图像中查找结构并不能给出所需的结果_Python_Python 2.7_Image Processing_Image Morphology - Fatal编程技术网

python中的命中或未命中形态学在图像中查找结构并不能给出所需的结果

python中的命中或未命中形态学在图像中查找结构并不能给出所需的结果,python,python-2.7,image-processing,image-morphology,Python,Python 2.7,Image Processing,Image Morphology,我正在使用形态学软件包创建我们正在使用的图像的骨架化版本。我们能够检测骨架化版本中的端点,但也希望能够检测结构生成新分支的点。我们首先尝试用3种不同的矩阵来检测它们,分别命名为h1、h2、h3。现在我们没有为过滤填充未命中矩阵,这是我们稍后将尝试添加的内容。如果我们想稍后尝试过滤,我们将使用5x5矩阵以便于编辑 问题是,即使骨架化版本中存在矩阵h1和h2中的模式,也无法检测它们。矩阵h3确实起作用。 我似乎不明白为什么会这样 def branches(img_pruned,cropped_ima

我正在使用形态学软件包创建我们正在使用的图像的骨架化版本。我们能够检测骨架化版本中的端点,但也希望能够检测结构生成新分支的点。我们首先尝试用3种不同的矩阵来检测它们,分别命名为h1、h2、h3。现在我们没有为过滤填充未命中矩阵,这是我们稍后将尝试添加的内容。如果我们想稍后尝试过滤,我们将使用5x5矩阵以便于编辑

问题是,即使骨架化版本中存在矩阵h1和h2中的模式,也无法检测它们。矩阵h3确实起作用。 我似乎不明白为什么会这样

def branches(img_pruned,cropped_image):
img = img_pruned
nbranches = 0
branches = cropped_image

h1 = [
    [0,0,0,0,0],
    [0,0,0,1,0],
    [0,1,1,0,0],
    [0,0,1,0,0],
    [0,0,0,0,0]]
h2 = [
    [0,0,0,0,0],
    [0,1,0,1,0],
    [0,0,1,0,0],
    [0,0,1,0,0],
    [0,0,0,0,0]]
h3 = [
    [0,0,0,0,0],
    [0,1,1,1,0],
    [0,0,1,0,0],
    [0,0,0,0,0],
    [0,0,0,0,0]]
m1 = [[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0]]

hitlist = []
misslist = []

for i in range(4):
    hitlist.append(np.rot90(h1, i))
    hitlist.append(np.rot90(h2, i))
    hitlist.append(np.rot90(h3, i))
for t in range(12):
    misslist.append(m1)

for hit,miss in zip(hitlist,misslist):
    branchimg = m.binary_hit_or_miss(img,hit,miss)

for y in range(len(branchimg)):
    for x in range(len(branchimg[y])):
        if branchimg[y][x]:
            nbranches +=1
            branches[y][x] = (0,0,255)

print nbranches
return branches
我们拍摄的原始图像

图片:

在骨骼化的照片中,我们还使用修剪使末端(分支的端点)更平滑


我不能完全确定命中与否-这可能与h1、h2和h3阵列中填充了0有关?无论如何,我将回答如何找到分支点,这不使用命中或未命中

基本思想是,表示分支点的任何像素都应该有3个或更多的邻居。相比之下,仅仅沿着一条路径的任何像素应该正好有两个邻居

<>如果你只考虑正交邻居作为真实邻居,找到3个或更多邻居的所有像素,这将是非常简单的。只需使用看起来像加号的内核K1卷积原始图像:

0 1 0
1 1 1
0 1 0
并查找值为4或更大的任何像素(3个相邻像素+中心像素)。代码如下所示:

import numpy as np
import scipy.ndimage as snd
K1 = snd.generate_binary_structure(2,1)
A = your_binary_image
B = snd.convolve(1*A,K1, mode='constant')
image_of_branch_points = B>=4
(我们在卷积中使用mode='constant',以避免默认的镜像边界条件在数据集的边缘给我们带来误报……这在您的数据集中似乎不是一个问题,因为它不会直接到达边缘,但请注意)(另一个快速提示:请注意卷积中的1*A…如果将A保留为布尔数据类型,它将不会生成任何大于1的结果,因此如果尚未生成,则必须将其转换为int)

但您似乎也允许对角连接/分支。这使它变得更复杂。我的第一个想法是只使用上述代码,但使用所有1的内核(我们称之为K2)(即允许沿对角线连接),如下所示:

但是,以下是一个基于上述方法的线段示例,该线段可能看起来像一个分支点,但实际上不是:

0 0 0 1 0
0 0 0 1 0
0 0 1 1 0
0 1 0 0 0
0 1 0 0 0
当与K2卷积时,这里的中心像素将显示为4,但检查表明它不是一个分支点。然后,这变得有点棘手

一种解决方案是使用蛮力:沿着每个分支移动到最近的邻居,直到找到两个邻居(不包括刚得到的像素)。然后继续沿着这些分支走至少两步,直到你确定你已经分叉成两个不同的分支。如果是这样,将分叉点标记为一个分支点。我不会在这里讨论暴力解决方案,但这是一种可能性

另一个解决方案是对内核K2使用上述方法,并根据原始图像手动检查每个分支点,丢弃视觉上不是分支点的任何分支点。我认为标记为分支点的大多数像素都是正确的,您只需要丢弃少数。如果您只处理少数dat这可能不是一个坏主意,但是如果你正在开发你打算在将来处理大量数据的代码,这不是一个很好的解决方案

第三种解决方案是单独使用此卷积方法,使用分支结构的每个可能排列的内核。您似乎已经编写了一些(h1、h2和h3)。如果您已经编写了所有可能的分支可能性,那么这可能是最快实现的方法:

image_of_branch_points = np.zeros_like(A)
list_of_kernels = [h1, h2, h3, ......]
for h in list_of_kernels:
    B = snd.convolve(A,h)
    image_of_branch_points += B
最后,第四种解决方案,也是我最喜欢的一种:对数据进行按摩,使内核K1能够工作,也就是说,使所有“真正”的相邻像素都是正交连接的,而不是对角连接的。这里有一个大致的方法,可能可以做到这一点。我希望我有你的原始图像,这样我就可以测试它了

基本上通过将以下两个内核分别与图像卷积:

0 0 0    0 0 0
0 0 1    1 0 0
0 1 0    0 1 0
在中心像素的结果为2的任何地方,你都知道你坐在一条对角线路径上,我们覆盖了对角线路径的两个可能斜率。通过在原始图像中向中心像素写入1,我们将对角线路径固定为正交连接(例如,一条长对角线将成为楼梯)。即使中心像素已为1,也可以再次将其覆盖为1,这无关紧要。因此,此代码应执行以下操作:

import numpy as np
import scipy.ndimage as snd

A = your_binary_image_as_ndarray
A_orthog = A.copy() #this will be the copy we update to have orthogonal neighbors
#Two diagonal kernels
K_diag_upslope = np.array([[0,0,0],[0,0,1],[0,1,0]])
K_diag_downslope = np.array([[0,0,0],[1,0,0],[0,1,0]])
#Convolve each one, one at a time, and save new points to A_orthog
#Note: the variable B is always an intermediary so I overwrite it every time
B = snd.convolve(1*A,K_diag_upslope, mode='constant')
A_orthog[B==2] = 1
B = snd.convolve(1*A,K_diag_downslope, mode='constant')
A_orthog[B==2] = 1

#Now A_orthog should be ready for the method shown in my first bit of code up above

K1 = snd.generate_binary_structure(2,1)
B = snd.convolve(1*A_orthog,K1, mode='constant')
image_of_branch_points = B>=4
我不能保证它在每种情况下都能工作,但对我来说,它在简单的测试用例中工作——例如,获取应用于身份矩阵的
np.identity(5)
的过程产生了以下结果:

1, 0, 0, 0, 0
1, 1, 0, 0, 0
0, 1, 1, 0, 0
0, 0, 1, 1, 0
0, 0, 0, 1, 1
当然,您应该保留原始的A-around-A_正交只是查找分支点的中介,并且分支点的图像_仍然应该对应于A上的正确分支点

请务必让我知道这是否对你有效。就像我说的,我没有适当的测试数据来强调测试这个想法,因为你的图像中可能隐藏着许多可能性,但我发现这个问题非常有趣。我之前已经处理过这个问题,但只在具有所有正交邻居的系统中

编辑:

我抓取了你的jpg图像并对其进行阈值处理,以得到一个二进制图像来测试我的代码。它基本上是有效的,虽然它确实给出了一些多个分支点的集群——这是不合理的,在分支混乱的地方。jpg不是二进制数据的最佳格式,所以我也不能100%确定是否存在jpg艺术
1, 0, 0, 0, 0
1, 1, 0, 0, 0
0, 1, 1, 0, 0
0, 0, 1, 1, 0
0, 0, 0, 1, 1
Abranch = 120*A + 240*image_of_branch_points

import matplotlib.pyplot as plt

cmap = plt.cmap.OrRd
cmap.set_under(color='black')
plt.imshow(Abranch, interpolation='none', cmap=cmap, vmin=0.01)