注記
完全なサンプルコードをダウンロードするには、こちらへ またはBinder経由でブラウザでこのサンプルを実行します。
ピクセルグラフを用いた物体の測地中心の算出#
様々な画像解析において、画像のピクセル、または画像領域のピクセルを、各ピクセルがその近傍(対角線を含む場合と含まない場合がある)に接続されたネットワークまたはグラフとして考えることが有用です。そのような状況の1つは、物体の測地中心を見つけることです。これは、直線ではなく、物体のピクセル上でのみ移動が許可されている場合、他のすべての点に最も近い点です。この点は、ネットワークにおける最大の近接中心性[1]を持つ点です。
この例では、スケルトンのそのようなピクセルグラフを作成し、そのスケルトンの中心ピクセルを見つけます。これは、実際にはオブジェクトの外側に落ちる可能性のある重心(質量中心とも呼ばれる)と比較して、その有用性を示しています。
参考文献#
import matplotlib.pyplot as plt
import numpy as np
from scipy import ndimage as ndi
from skimage import color, data, filters, graph, measure, morphology
まず、データを読み込みます:人間の網膜の画像です。
retina_source = data.retina()
_, ax = plt.subplots()
ax.imshow(retina_source)
ax.set_axis_off()
_ = ax.set_title('Human retina')

画像をグレースケールに変換し、次にSato 血管らしさ フィルタ
を使用して、画像内の主要な血管をより明確に区別します。
retina = color.rgb2gray(retina_source)
t0, t1 = filters.threshold_multiotsu(retina, classes=3)
mask = retina > t0
vessels = filters.sato(retina, sigmas=range(1, 10)) * mask
_, axes = plt.subplots(nrows=1, ncols=2)
axes[0].imshow(retina, cmap='gray')
axes[0].set_axis_off()
axes[0].set_title('grayscale')
axes[1].imshow(vessels, cmap='magma')
axes[1].set_axis_off()
_ = axes[1].set_title('Sato vesselness')

観察された血管らしさの値に基づいて、ヒステリシス 閾値処理
を使用して、主要な血管を定義します。
thresholded = filters.apply_hysteresis_threshold(vessels, 0.01, 0.03)
labeled = ndi.label(thresholded)[0]
_, ax = plt.subplots()
ax.imshow(color.label2rgb(labeled, retina))
ax.set_axis_off()
_ = ax.set_title('Thresholded vesselness')

最後に、このラベル画像をスケルトン化
し、それを基にして、そのスケルトン内の中心 ピクセル
を見つけます。それを重心の位置と比較してください!
largest_nonzero_label = np.argmax(np.bincount(labeled[labeled > 0]))
binary = labeled == largest_nonzero_label
skeleton = morphology.skeletonize(binary)
g, nodes = graph.pixel_graph(skeleton, connectivity=2)
px, distances = graph.central_pixel(
g, nodes=nodes, shape=skeleton.shape, partition_size=100
)
centroid = measure.centroid(labeled > 0)
_, ax = plt.subplots()
ax.imshow(color.label2rgb(skeleton, retina))
ax.scatter(px[1], px[0], label='graph center')
ax.scatter(centroid[1], centroid[0], label='centroid')
ax.legend()
ax.set_axis_off()
ax.set_title('Vessel graph center vs centroid')
plt.show()

**スクリプトの実行時間合計:**(1分22.863秒)