注意
转到末尾 下载完整的示例代码。或通过 Binder 在浏览器中运行此示例
形状指数#
形状指数是局部曲率的单值度量,源自 Hessian 的特征值,由 Koenderink & van Doorn 定义 [1].
它可用于根据其表观局部形状查找结构。
形状指数映射到 -1 到 1 之间的值,表示不同类型的形状(有关详细信息,请参阅文档)。
在此示例中,生成了一个带有斑点的随机图像,应检测这些斑点。
形状指数 1 代表“球形帽”,即我们要检测的斑点的形状。
最左侧的图显示了生成的图像,中间显示了图像的 3D 渲染,将强度值作为 3D 表面的高度,最右侧显示了形状指数 (s)。
如您所见,形状指数很容易放大噪声的局部形状,但不受全局现象(如不均匀照明)的影响。
蓝色和绿色标记是与所需形状的偏差不超过 0.05 的点。为了衰减信号中的噪声,绿色标记取自经过另一次高斯模糊处理后的形状指数 (s)(得出 s')。
请注意,相互连接过密的斑点没有被检测到,因为它们不具有所需的形状。
import numpy as np
import matplotlib.pyplot as plt
from scipy import ndimage as ndi
from skimage.feature import shape_index
from skimage.draw import disk
def create_test_image(image_size=256, spot_count=30, spot_radius=5, cloud_noise_size=4):
"""
Generate a test image with random noise, uneven illumination and spots.
"""
rng = np.random.default_rng()
image = rng.normal(loc=0.25, scale=0.25, size=(image_size, image_size))
for _ in range(spot_count):
rr, cc = disk(
(rng.integers(image.shape[0]), rng.integers(image.shape[1])),
spot_radius,
shape=image.shape,
)
image[rr, cc] = 1
image *= rng.normal(loc=1.0, scale=0.1, size=image.shape)
image *= ndi.zoom(
rng.normal(loc=1.0, scale=0.5, size=(cloud_noise_size, cloud_noise_size)),
image_size / cloud_noise_size,
)
return ndi.gaussian_filter(image, sigma=2.0)
# First create the test image and its shape index
image = create_test_image()
s = shape_index(image)
# In this example we want to detect 'spherical caps',
# so we threshold the shape index map to
# find points which are 'spherical caps' (~1)
target = 1
delta = 0.05
point_y, point_x = np.where(np.abs(s - target) < delta)
point_z = image[point_y, point_x]
# The shape index map relentlessly produces the shape, even that of noise.
# In order to reduce the impact of noise, we apply a Gaussian filter to it,
# and show the results once in
s_smooth = ndi.gaussian_filter(s, sigma=0.5)
point_y_s, point_x_s = np.where(np.abs(s_smooth - target) < delta)
point_z_s = image[point_y_s, point_x_s]
fig = plt.figure(figsize=(12, 4))
ax1 = fig.add_subplot(1, 3, 1)
ax1.imshow(image, cmap=plt.cm.gray)
ax1.axis('off')
ax1.set_title('Input image')
scatter_settings = dict(alpha=0.75, s=10, linewidths=0)
ax1.scatter(point_x, point_y, color='blue', **scatter_settings)
ax1.scatter(point_x_s, point_y_s, color='green', **scatter_settings)
ax2 = fig.add_subplot(1, 3, 2, projection='3d', sharex=ax1, sharey=ax1)
x, y = np.meshgrid(np.arange(0, image.shape[0], 1), np.arange(0, image.shape[1], 1))
ax2.plot_surface(x, y, image, linewidth=0, alpha=0.5)
ax2.scatter(
point_x, point_y, point_z, color='blue', label='$|s - 1|<0.05$', **scatter_settings
)
ax2.scatter(
point_x_s,
point_y_s,
point_z_s,
color='green',
label='$|s\' - 1|<0.05$',
**scatter_settings,
)
ax2.legend(loc='lower left')
ax2.axis('off')
ax2.set_title('3D visualization')
ax3 = fig.add_subplot(1, 3, 3, sharex=ax1, sharey=ax1)
ax3.imshow(s, cmap=plt.cm.gray)
ax3.axis('off')
ax3.set_title(r'Shape index, $\sigma=1$')
fig.tight_layout()
plt.show()
脚本的总运行时间:(0 分钟 0.951 秒)