マスク付き正規化相互相関#

この例では、マスク付き正規化相互相関を使用して、無効なデータを含む2つの類似画像間の相対的なシフトを特定します。

この場合、マスクが計算に影響を与えるため、相互相関を計算する前に画像を単純にマスクすることはできません。マスクの影響は、[1]に記載されているように、相互相関から削除する必要があります。

この例では、2つの画像間の並進をレジストレーションします。ただし、一方の画像には約25%のピクセルが破損しています。

import numpy as np
import matplotlib.pyplot as plt

from skimage import data, draw
from skimage.registration import phase_cross_correlation
from scipy import ndimage as ndi

無効な画像の領域を定義します。無効なピクセルの確率は25%です。これは、欠陥のある検出器、または並進の影響を受けないエッジ(ウィンドウ内の移動オブジェクトなど)が原因である可能性があります。詳細については、参照論文を参照してください。

image = data.camera()
shift = (-22, 13)

rng = np.random.default_rng()
corrupted_pixels = rng.choice([False, True], size=image.shape, p=[0.25, 0.75])

# The shift corresponds to the pixel offset relative to the reference image
offset_image = ndi.shift(image, shift)
offset_image *= corrupted_pixels
print(f'Known offset (row, col): {shift}')

# Determine what the mask is based on which pixels are invalid
# In this case, we know what the mask should be since we corrupted
# the pixels ourselves
mask = corrupted_pixels

detected_shift, _, _ = phase_cross_correlation(image, offset_image, reference_mask=mask)

print(f'Detected pixel offset (row, col): {-detected_shift}')

fig, (ax1, ax2, ax3) = plt.subplots(1, 3, sharex=True, sharey=True, figsize=(8, 3))

ax1.imshow(image, cmap='gray')
ax1.set_axis_off()
ax1.set_title('Reference image')

ax2.imshow(offset_image.real, cmap='gray')
ax2.set_axis_off()
ax2.set_title('Corrupted, offset image')

ax3.imshow(mask, cmap='gray')
ax3.set_axis_off()
ax3.set_title('Masked pixels')


plt.show()
Reference image, Corrupted, offset image, Masked pixels
Known offset (row, col): (-22, 13)
Detected pixel offset (row, col): [-22.  13.]

ソリッドマスクは、別の例を示すものです。この場合、画像の限定されたビューとオフセットされた画像があります。これらの画像のマスクは同じである必要はありません。phase_cross_correlation関数は、画像のどの部分を比較する必要があるかを正しく識別します。

image = data.camera()
shift = (-22, 13)

rr1, cc1 = draw.ellipse(259, 248, r_radius=125, c_radius=100, shape=image.shape)

rr2, cc2 = draw.ellipse(300, 200, r_radius=110, c_radius=180, shape=image.shape)

mask1 = np.zeros_like(image, dtype=bool)
mask2 = np.zeros_like(image, dtype=bool)
mask1[rr1, cc1] = True
mask2[rr2, cc2] = True

offset_image = ndi.shift(image, shift)
image *= mask1
offset_image *= mask2

print(f'Known offset (row, col): {shift}')

detected_shift, _, _ = phase_cross_correlation(
    image, offset_image, reference_mask=mask1, moving_mask=mask2
)

print(f'Detected pixel offset (row, col): {-detected_shift}')

fig = plt.figure(figsize=(8, 3))
ax1 = plt.subplot(1, 2, 1)
ax2 = plt.subplot(1, 2, 2, sharex=ax1, sharey=ax1)

ax1.imshow(image, cmap='gray')
ax1.set_axis_off()
ax1.set_title('Reference image')

ax2.imshow(offset_image.real, cmap='gray')
ax2.set_axis_off()
ax2.set_title('Masked, offset image')

plt.show()
Reference image, Masked, offset image
Known offset (row, col): (-22, 13)
Detected pixel offset (row, col): [-22.  13.]

スクリプトの総実行時間:(0分1.105秒)

Sphinx-Galleryによって生成されたギャラリー