我想为不规则的三维图像添加边框,该图像存储为二进制numpy数组。我想过可能将图像左/右,前/后,上/下移动,然后组合这6个图像并减去原始图像;使用以下代码:
#make copy of the image shifted one voxel to the left
image_border = np.zeros((img_dim[0], img_dim[1], img_dim[2]))
for x in xvoxels:
x_slice_original = image[x, :, :]
x_slice_new = np.zeros((img_dim[1], img_dim[2]))
for y in yvoxels:
for z in zvoxels:
if x_slice_original[y, z] == 1:
x_slice_new[(y-1), z] = 1
else:
x_slice_new[(y-1), z] = 0
image_border[x, :, :] = x_slice_new
这似乎有点低效,但是想知道是否有人有更整洁的解决方案?
编辑: 该图像是MRI图像91 * 109 * 91体素。 xvoxels和zvoxels是0:90的列表,yvoxels是0:108的列表。有问题的图像的2D切片如下:
答案 0 :(得分:0)
这是一个使用scipy.ndimage.binary_dilation
的非常简单的方法,它本质上是您所考虑的操作的库版本。剩下要做的就是将原始体素清空。正如你所看到的那样,整个事物在一条线上舒适地适合。
import numpy as np
from scipy import ndimage
# create mock data
i,j,k = np.ogrid[:10,:10,:10]
ball = ((i-5)**2+(j-5)**2+(k-5)**2 < 16).view(np.int8)
# create border
shell = (ndimage.binary_dilation(ball) & ~ball).view(np.int8)
# that's all folks, show one section of original and border
print(ball[5])
# [[0 0 0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0 0 0]
# [0 0 0 1 1 1 1 1 0 0]
# [0 0 1 1 1 1 1 1 1 0]
# [0 0 1 1 1 1 1 1 1 0]
# [0 0 1 1 1 1 1 1 1 0]
# [0 0 1 1 1 1 1 1 1 0]
# [0 0 1 1 1 1 1 1 1 0]
# [0 0 0 1 1 1 1 1 0 0]
# [0 0 0 0 0 0 0 0 0 0]]
print(shell[5])
# [[0 0 0 0 0 0 0 0 0 0]
# [0 0 0 1 1 1 1 1 0 0]
# [0 0 1 0 0 0 0 0 1 0]
# [0 1 0 0 0 0 0 0 0 1]
# [0 1 0 0 0 0 0 0 0 1]
# [0 1 0 0 0 0 0 0 0 1]
# [0 1 0 0 0 0 0 0 0 1]
# [0 1 0 0 0 0 0 0 0 1]
# [0 0 1 0 0 0 0 0 1 0]
# [0 0 0 1 1 1 1 1 0 0]]
答案 1 :(得分:0)
您想要做的是一个名为'扩张'的过程。对于二进制图像,您的想法是循环遍历图像中的所有像素。如果像素为“True”,则在其周围创建一组指定像素也为“True”(由“内核”或“结构”定义)。例如
0,0,0,0,0
0,0,0,0,0
0,0,1,1,0
0,0,0,0,0
0,0,0,0,0
带内核
0,1,0
1,1,1
0,1,0
当达到(2,2)时,它变为:
0,0,0,0,0
0,0,1,0,0
0,1,1,1,0
0,0,1,0,0
0,0,0,0,0
到达(2,3)时变为:
0,0,0,0,0
0,0,1,1,0
0,1,1,1,1
0,0,1,1,0
0,0,0,0,0
您可以重复此操作,或使用其他内核。例如:
import scipy.ndimage
import numpy as np
import matplotlib.pyplot as plt
im = np.zeros((90,90),dtype='bool')
im[30:61,30:61] = True
fig = plt.figure(figsize=(18,6))
fig.set_tight_layout(True)
fig.add_subplot(1,3,1)
plt.imshow(im,interpolation='nearest')
fig.add_subplot(1,3,2)
plt.imshow(scipy.ndimage.binary_dilation(im,iterations=4),interpolation='nearest')
fig.add_subplot(1,3,3)
plt.imshow(scipy.ndimage.binary_dilation(im,iterations=4,structure=np.ones((3,3))),interpolation='nearest')
plt.show()
结果:
当然,获取“外部”边界只是扩张图像和原始图像的差异。