チャネルファーストデータをチャネルラストにする


はじめに

Pytorchを前提に記述されたプログラムをKerasに書き換えている時に、画像データ配列の軸を入れ替える必要があったため、その方法について共有します。

Image Channel Order

Channels First : (N, C, H, W) ← PyTorch
Channels Last : (N, H, W, C) ← Keras

N : 画像の枚数
C : チャネル数(色など)
H : 画像のHeight
W : 画像のWidth

チャネルファースト(Channels First)

PyTorchなどにおいて、画像データ配列でモデルを学習する際は、Channels First 形式が一般的です。画像の次元の並び方が (Channel, Height, Width)となっています。Channel(Color)の次元が配列の先頭にあることが名前からわかります。

チャネルラスト(Channels Last)

Keras,PIL,OpenCVなどにおいて、画像データ配列を扱う場合は、Channels Last 形式が一般的です。画像の次元の並び方が (Height, Width, Channel)となっています。Channelの次元が配列の最後にあることが名前からわかります。

Channels First → Channels Last

仮の Channels First の画像配列データを作成します。

仮の画像配列データ
img = np.arange(100*64*64*3).reshape(-1,3,64,64)
img.shape 
(100, 3, 64, 64)

方法1 : np.transpose()

np.transpose()
%%timeit
img.transpose(0,2,3,1).shape
(100, 64, 64, 3)
791 ns ± 92.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

方法2 : np.swapaxes()

np.swapaxes()
%%timeit
np.swapaxes(img, 1, 3).shape
(100, 64, 64, 3)
1.54 µs ± 410 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

方法3 : np.moveaxes()

np.moveaxes()
%%timeit
np.moveaxes(img, 1, 3).shape
(100, 64, 64, 3)
9.29 µs ± 956 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

方法4 : np.rollaxes()

np.rollaxes()
%%timeit
np.rollaxes(img, 1, 4).shape
(100, 64, 64, 3)
2.89 µs ± 358 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

方法5 : np.einsum()

np.einsum()
%%timeit
np.einsum('ijkl->ilkj', img).shape
(100, 64, 64, 3)
1.77 µs ± 210 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

最後に

np.transpose() が最速でした。お好きなのを使用してください。

what-is-the-correct-way-to-change-image-channel-ordering-between-channels-first を参考にしました。