Chapter 04

画像の類似度を求めよう

eetann / えーたん
eetann / えーたん
2020.12.09に更新

この章の概要

モザイクアート化したい画像とブロック画像がどのくらい似ているか、を測るために画像の類似度を計算します。

類似度の計算方針

モザイクアートでは、色あいが似ている画像を置き換えます。
モザイクアートの説明

まず、RGBからCIE L*a*b色空間へと変換して色差を求めます
CIE L*a*bは、人間の色の変化の感じ方に合った色空間です。L* が明度、a*が緑~赤の色味、b*が青~黄の色味を表現します。
色空間の変換はskimageのcolor.rgb2labを利用します。式変形などを詳しく知りたい方はこちら

画素の類似度

色が似ている = 色差(2画素のL*a*b成分ごとの差)が小さい とします。
ある画素1(L_1^*, a_1^*, b_1^*)とある画素2(L_2^*, a_2^*, b_2^*)の色差\Deltaは、以下の式で求められます。

\Delta=\sqrt{(L_2^* - L_1^*)^2 + (a_2^* - a_1^*)^2 + (b_2^* - b_1^*)^2}

急に難しくなってきたぁ、と感じる方もいるかもしれません。画素1と画素2のユークリッド距離です。怖くない。怖くないぞ!
画素の類似度

この色差 \Delta についても、
skimageのcolor.deltaE_cie76を利用して求めることができます。一体何者なんだskimage。

画像の類似度

画素の類似度を使って、画像の類似度を計算したいと思います。手順は、

  1. 比べる2つ画像のひとつひとつの画素に対して、L*a*b*色空間の色差を求める
  2. すべての色差の合計を計算する

です。色差が小さい画像同士が似ている、ということにします。
これを式で表すと、

S=\sum_{i=1}^{N} \sum_{j=1}^{M} \sqrt{(L_{ij} - L_{ij}')^2 + (a_{ij} - a_{ij}')^2 + (b_{ij} - b_{ij}')^2}

ただし、Nを画像の縦の長さ、Mを横の長さ、L,L'をL*a*b*空間のL*成分、a,a'をa*成分、b,b'をb*成分としました。

実際に、モザイクアートにしたい画像を使って類似度を計算する関数を書きます。
まずは適当に3枚の画像II_G80I_B80を用意します。

I_G80 = I.copy()
I_G80[:, :, 1] = I_G80[:, :, 1] * 0.8
I_B80 = I.copy()
I_B80[:, :, 2] = I_B80[:, :, 2] * 0.8
plt.subplot(1, 3, 1)
plt.imshow(I)
plt.subplot(1, 3, 2)
plt.imshow(I_G80)
plt.subplot(1, 3, 3)
plt.imshow(I_B80)
plt.gcf().set_size_inches(15, 15)
plt.show()

Iは、一番最初に取得した例の画像です。
I_G80は、一旦Iをコピーし、G成分を80%にしています。
同様にI_B80では、B成分を80%にしています。
plt.gcf().set_size_inches(15, 15)で適当に拡大表示します。
成分をいじった画像

左からII_G80I_B80です。
I_G80はなんだか赤っぽいですね。II_G80よりもII_B80のほうが色的に似てます。これらについて、実際に先程の類似度を計算して求めます。

import skimage.color
I_Lab = skimage.color.rgb2lab(I)
I_G80Lab = skimage.color.rgb2lab(I_G80)
I_B80Lab = skimage.color.rgb2lab(I_B80)
print("I_Lab, I_Lab", np.sum(skimage.color.deltaE_cie76(I_Lab, I_Lab)))
print("I_Lab, I_G80Lab", np.sum(skimage.color.deltaE_cie76(I_Lab, I_G80Lab)))
print("I_Lab, I_B80Lab", np.sum(skimage.color.deltaE_cie76(I_Lab, I_B80Lab)))

出力は以下です。

I_Lab, I_Lab 0.0
I_Lab, I_G80Lab 3334620.9965976127
I_Lab, I_B80Lab 1733027.0011780516

I_Lab 同士は同じ画像なので色差は当然0です。
また、色差が小さいII_B80のほうが、II_G80よりも似ていると言えます。