こんにちは、技術開発の三浦です。
夏になると子どもの頃に図書館に行ったことを思い出します。自由研究のネタを探しに夏休みによく行きました。図書館はクーラーが効いていて涼しくて、暑い中たどり着いて図書館の中に入った時の心地よさは今でも覚えています。
今回は以前から気になっていたあることを、夏の自由研究として試してみたのでご紹介します!
CIFAR-10とビーズ
CIFAR-10は10クラスで構成された32x32のカラー画像のデータセットです。画像系の深層学習では、サイズが小さめで扱いやすいことから実験目的で非常によく利用されています。 私も何か新しいアルゴリズムを試す時にはCIFAR-10のデータを使うことが多いです。
さて、そんなCIFAR-10の画像ですが、見ていていつも思うことがありました。
CIFAR-10の画像をビーズで作ってみたい
です。
32x32と小さいのにバラエティに富んでいて、これがビーズの作品になって手で触れることが出来たらすごくいいのに、と思っていました。我が家には子どもと遊ぶために「アイロンで固めるタイプのビーズ」があります。 このビーズを使って夏本番の今、大人の自由研究としてCIFAR-10の画像をビーズで作ることが出来るかチャレンジしてみました。
画像をビーズで表現する
まず、我が家にあるビーズセットを取り出して眺めてみました。
画像をビーズで表現するためには、画像を構成するピクセルをこのビーズセットのどれかの色に置き換えないといけません。つまりピクセルの色に対し、それと全てのビーズの色の近さを調べ、一番色が近いビーズがどれかを探す必要があります。この方法について、調べる必要がありました。
またアイロンで固めるタイプのビーズ作品は、ビーズをプレートに並べて作るのですが、我が家にあるプレートのサイズは32x32よりも小さいため、画像のサイズを小さくする必要があります。今回は24x24のサイズにリサイズすることにしました。
以上を踏まえると、画像をビーズで表現するために必要になる作業は以下のようになりました。
- 画像を32x32から24x24にリサイズする
- 画像の各ピクセルを手持ちのビーズの中で一番近い色のものに置き換える
- ピクセルに対応するビーズの番号を持つ24x24の行列データをプリントアウトする
- あとは頑張ってビーズを並べてアイロンで固める
色の近さの測定について
さて、とにもかくにも調べないといけないのが、画像のピクセルに対して最も近い色のビーズを探すための「色の近さを測定する」方法です。
色の近さは色差と呼ばれています。私は最初、色はRGBの3次元空間上で表現出来るので、 その近さを単純にユークリッド距離で求めればいいのでは、と考えていました。しかし実際にはそれでは上手くいかず、たとえ2つの色の間のユークリッド距離が同じであったとしても、色によって人の目には大きな違いがあるように見えたり、反対に違いが認識できないことがあります。例えば色の彩度が高い領域では人にとっては色の違いが分かりにくくなってしまう、という傾向があるそうです。
色の違いの測定についてはKONICA MINOLTA様のこちらのページがとても参考になりました。
新しい色差式(CIE DE2000)について。-楽しく学べる知恵袋 | コニカミノルタ
人の色識別能力に合わせた色差測定式として「CIE DE2000」というものがあり、この計算式を用いることで人の認識に近い、色の近さを測定することが出来ることが分かりました。この計算処理はPythonの画像処理ライブラリ「scikit-image」で利用できるため、今回の実験の画像処理は「scikit-image」を利用することにしました。
似た色のビーズを探すための準備
似た色のビーズを見つけ出す方法が分かったので、そのためにも持っているビーズの色を数値化しなければなりません。上手な方法が思いつかなかったので、ビーズが入ったビーズケースの写真を撮り、ペイントソフトで各ビーズの色のRGB値を1つ1つ調べていきました。調べた結果はPythonのlistの形式で記録していきました。
そしてビーズケースの写真から各ビーズの色をこのように抽出することが出来ました。
持っているビーズのうち、透明のものを除く計47色のデータを集めました。
画像処理のプログラム
CIFAR-10に含まれる以下の「horse」の画像に対して処理を施していきました。
画像を24x24にリサイズし、所持しているビーズの色47色に置き換えるプログラムを以下のように作成しました。
from skimage import io from skimage.color import deltaE_ciede2000, rgb2lab from skimage.transform import resize import json size = 24 # 画像変換サイズ # 抽出したビーズカラーデータの読み込み colors = json.load(open('data/colors.json')) colors = np.array(colors,dtype=np.uint8) colors = colors / 255.0 corlos_lab = rgb2lab(colors) #「CIE DE2000」のためピクセルをLab色空間に変換 # CIFAR-10の対象画像の変換 original_img = cifar_data[target_img] #CIFAR-10データセットから1枚選択 transform_img = resize(original_img,(size,size),anti_aliasing=False) #24x24にリサイズ transform_img_lab = rgb2lab(transform_img) #「CIE DE2000」のためピクセルをLab色空間に変換 # 「CIE DE2000」による色差計算 color_diff = deltaE_ciede2000( np.expand_dims(transform_img_lab, axis=2), corlos_lab.reshape((1,1,-1,3)) ) # colorsの中で最も色差距離の近い色を選び置き換える output_img = colors[color_diff.argmin(axis=-1)] io.imshow(output_img) print(color_diff.argmin(axis=-1))
上の結果、得られた画像がこちらです。
上手くビーズ用に変換が出来たようです!
プリントアウトしてビーズを置いていく
変換した画像と、どこにどのビーズを置くのかを番号で指定した行列をこのように並べ、プリントアウトしました。
さらにどのビーズが何番か分かるようにビーズケースに番号を書きました。
そしたらこのようにプリントアウトした用紙にビーズのプレートを置いて・・・
ビーズを置いていきます。
1時間くらいかかって全てのビーズを置き終えました。
最後にくっつき防止のシートの上からアイロンをかけて、熱が冷めたら完成です!
元の画像と並べてみると、このような感じになりました。
完成したビーズ作品は、遠くに置いて見るとそれなりに再現が出来ていて、いつもパソコンの中で見ていたCIFAR-10の画像に手で触れることが出来てとても満足しています。
以上真夏のとある休日に行った、自由研究のレポートでした。
まとめ
ということで、今回はいつも深層学習でお世話になっているCIFAR-10の画像をビーズでどうやって再現できるのかについて調べて確かめてみました。
近い色を探し出す方法は今まで知らなかったので、とてもいい勉強になりました。調べていると色に関する研究はかなり奥が深そうで、もっと時間をかけて理解しないと、と感じています。画像にどんな色が含まれているのかを調べることで、画像が持つ特徴をより理解することが出来そうです。
せっかく新しいことを知ることが出来たので、今後の業務でも活用していきたいと思います!