Chapter 07

モザイクアートの完成

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

この章の概要

モザイクアートを完成させます。

ブロック画像を分割画像のサイズに合わせる

APIで取得した画像がグレースケールだった場合は使わないことにします。

n = 0
URLnums = []
Ibs = np.zeros((row1_size, col1_size, 3, 500))
for i, U in enumerate(imageURLs):
    try:
        Iu = skimage.io.imread(U)
    except:
        continue
    if len(Iu.shape) == 2:
        continue
    URLnums.append(i)
    Ibs[:, :, :, n] = trisize(row1_size, col1_size, Iu)
    n += 1
Ibs = Ibs[:, :, :, :n]

print(n)
plt.imshow(Ibs[:, :, :, 0])
plt.show()

Ibsに画像を入れました。
グレースケールの画像や画像読み込みエラーが出た場合は飛ばすため、Ibsの画像がimageURLsのどのインデックスと対応しているかを表すURLnumsも作りました。飛ばしているのはエラーだけで、警告が出る画像もあります。
試しにIbs[:, :, :, 0]を表示してみました。
Ibsの0

元の画像も表示して比べてみると、画像の大部分が削られています。ここについては改善の余地がありそうですが本書では扱いません。

plt.imshow(skimage.io.imread(imageURLs[URLnums[0]]))
plt.show()

URLnumsの0

ブロック画像を8x8のL*a*bに変換

かわいいかわいいブロック画像たちをsmall_lab()で変換します。

slabs = np.zeros((8, 8, 3, n))
for i in range(n):
    slabs[:, :, :, i] = small_lab(Ibs[:, :, :, i])

各分割画像と最も似ているブロック画像を探し、置き換える

最後に、分割した画像と似ているブロック画像を探し、置き換えることでモザイクアートを生成します。

IM = np.zeros((row_split*row1_size, col_split*col1_size, 3))
for row in range(row_split):
    for col in range(col_split):
        Im = small_lab(Ims[row, col, 0, :, :, :])
        min_diff = np.sum(skimage.color.deltaE_cie76(Im, slabs[:, :, :, 0]))
        min_idx = 0
        for i in range(1, n):
            diff = np.sum(skimage.color.deltaE_cie76(Im, slabs[:, :, :, i]))
            if diff < min_diff:
                min_diff = diff
                min_idx = i
        IM[(row*row1_size):((row+1)*row1_size), (col*col1_size):((col+1)*col1_size), :] = Ibs[:, :, :, min_idx]
plt.subplot(1, 2, 1)
plt.imshow(I)
plt.axis("off")
plt.subplot(1, 2, 2)
plt.imshow(IM)
plt.axis("off")
plt.gcf().set_size_inches(15, 15)
plt.show()

最初の2つのfor文で分割画像を走査、3つめのfor文で一番似ているブロック画像を探し、置き換えます。

無事モザイクアートが完成しました。
元画像とモザイクアート

最後に

"The Met Collection API" の画像を使いましたが、ぜひ自分で用意した画像でも試してみてください。
また、今回は雑にモザイクアートを作成しましたが、まだまだ改善点があります。

  • 同じブロック画像が何回も使われている
  • 一度も使われていないブロック画像がある
  • ブロック画像を分割画像のサイズに合わせるときに切り抜く領域が左か上に固定されている

これらを考慮して作るのも良いですね。