注記
最後まで移動して完全なサンプルコードをダウンロードするか、Binder経由でブラウザでこのサンプルを実行してください
オプティカルフローを用いたレジストレーション#
オプティカルフローを用いた画像レジストレーションのデモンストレーション。
定義上、オプティカルフローは、*image1(x+u, y+v) = image0(x, y)* を満たすベクトル場 (u, v) です。ここで、(image0, image1) はシーケンスの連続する2Dフレームの組です。このベクトル場は、画像ワーピングによってレジストレーションに使用できます。
レジストレーション結果を表示するために、レジストレーションの結果を赤チャネルに、ターゲット画像を緑および青チャネルに割り当てることで、RGB画像が構築されます。完全なレジストレーションではグレースケール画像になりますが、誤ってレジストレーションされたピクセルは構築されたRGB画像で色付きで表示されます。
import numpy as np
from matplotlib import pyplot as plt
from skimage.color import rgb2gray
from skimage.data import stereo_motorcycle, vortex
from skimage.transform import warp
from skimage.registration import optical_flow_tvl1, optical_flow_ilk
# --- Load the sequence
image0, image1, disp = stereo_motorcycle()
# --- Convert the images to gray level: color is not supported.
image0 = rgb2gray(image0)
image1 = rgb2gray(image1)
# --- Compute the optical flow
v, u = optical_flow_tvl1(image0, image1)
# --- Use the estimated optical flow for registration
nr, nc = image0.shape
row_coords, col_coords = np.meshgrid(np.arange(nr), np.arange(nc), indexing='ij')
image1_warp = warp(image1, np.array([row_coords + v, col_coords + u]), mode='edge')
# build an RGB image with the unregistered sequence
seq_im = np.zeros((nr, nc, 3))
seq_im[..., 0] = image1
seq_im[..., 1] = image0
seq_im[..., 2] = image0
# build an RGB image with the registered sequence
reg_im = np.zeros((nr, nc, 3))
reg_im[..., 0] = image1_warp
reg_im[..., 1] = image0
reg_im[..., 2] = image0
# build an RGB image with the registered sequence
target_im = np.zeros((nr, nc, 3))
target_im[..., 0] = image0
target_im[..., 1] = image0
target_im[..., 2] = image0
# --- Show the result
fig, (ax0, ax1, ax2) = plt.subplots(3, 1, figsize=(5, 10))
ax0.imshow(seq_im)
ax0.set_title("Unregistered sequence")
ax0.set_axis_off()
ax1.imshow(reg_im)
ax1.set_title("Registered sequence")
ax1.set_axis_off()
ax2.imshow(target_im)
ax2.set_title("Target")
ax2.set_axis_off()
fig.tight_layout()

推定されたベクトル場 (u, v) は、カレントプロットでも表示できます。
次の例では、反復Lukas-Kanadeアルゴリズム(iLK)が粒子画像速度測定法(PIV)の文脈で粒子の画像に適用されます。シーケンスは、PIVチャレンジ2001からのケースBです。
image0, image1 = vortex()
# --- Compute the optical flow
v, u = optical_flow_ilk(image0, image1, radius=15)
# --- Compute flow magnitude
norm = np.sqrt(u**2 + v**2)
# --- Display
fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(8, 4))
# --- Sequence image sample
ax0.imshow(image0, cmap='gray')
ax0.set_title("Sequence image sample")
ax0.set_axis_off()
# --- Quiver plot arguments
nvec = 20 # Number of vectors to be displayed along each image dimension
nl, nc = image0.shape
step = max(nl // nvec, nc // nvec)
y, x = np.mgrid[:nl:step, :nc:step]
u_ = u[::step, ::step]
v_ = v[::step, ::step]
ax1.imshow(norm)
ax1.quiver(x, y, u_, v_, color='r', units='dots', angles='xy', scale_units='xy', lw=3)
ax1.set_title("Optical flow magnitude and vector field")
ax1.set_axis_off()
fig.tight_layout()
plt.show()

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