類似画像検索の API というか機能というか、、を作っています。いずれはオープンソース化を念頭に入れているので、その成果もいずれ公開するつもりですが、今自分が作ろうとしている仕組みについて調べたことをまとめる目的で公開します。


類似画像検索では「ある2つの画像が似ているかどうか?」を数値で判断し、「こっちの画像よりもあっちの画像の方がより似ている」、「この画像に似ているのはこれとこれとこれと・・」みたいな識別ができるようにする必要があります。

その判断アルゴリズムにはいくつかの方法(基準)があります。おおまかに言うと「色合いが似てる」とか「輪郭が似てる」とかです。以下で紹介するカラーヒストグラムはそのひとつで、「同じような色合いの画像を似ていると判断する」方法です:
Color Histogram - Wikipedia


※この方法は「同じような色」の画像を「類似している」と判断します。輪郭や形を意識しているわけではありません。したがってあるカラー画像のモノクロ画像はあまり似ていない、という判断になると思います。また元の画像を中心から180度回転させたもの(上下逆さまにしたもの)は使っている色の構成自体は同じものなので「似ている」と判断することになります。


例えば横幅 W ピクセル、縦幅 H ピクセルの画像があったとします。ピクセル総数は W * H です。この ( W * H ) 個のピクセル毎に RGB 値を取得して、RGB の出現頻度のヒストグラム(階級度数分布)を作ります。ただし通常の RGB 値は #RRGGBB (RR, GG, BB は全て16進2桁の数)と表されるように R, G, B 各色毎に 256 種類の値を持ちますので、そのまま出現頻度を求めようとすると 256 * 256 * 256 = 16777216 種類もの出現パターンがあります。これだとカラーヒストグラムを作りにくい(傾向が出にくい)し、16777216 次元のベクトル演算が必要になるためちと面倒です。そこで各色毎の値を 4 種類として(つまり RR, GG, BB の各上位 2 ビットの値のみ使うように減色して)、4 * 4 * 4 = 64 次元のカラーヒストグラムを作ることにします。

あるピクセル ( x, y ) の RGB 値が #RRGGB という値であったとして、RR, GG, BB それぞれの上位2ビットを取得した結果が rr, gg, bb であったとします。このピクセルのカラー値 c(x,y) は 16 * rr + 4 * gg + bb で表すことができ、この値は 0 から 63 までの 64 種類の値を取り得ます。

この c(x,y) を全ての x と y(0 <= x < W, 0 <= y < H) について計算し、求めた c(x,y) の分布結果でカラーヒストグラムを作成します。例えばこの画像(314 * 340):
baseball


のカラーヒストグラム(分布表)を計算すると、以下のようになりました:
2017092001


カラーヒストグラムの見方は横軸が上記方法で計算したカラー値、縦軸がその出現個数です。一番左の数はカラー値が0、つまり「黒」の数で、一番右は「白」の数です。どうしてもこの2つの値は多くなりがちであると思いますが、それ以外にも点々とした箇所があり、これが画像の(色合いの)特徴を表しているわけです。

もう1つ、こちらの画像(340 * 340):
basketball



で同じカラーヒストグラムを作ると、以下のようになります:
2017092001


このようにしてあらかじめ画像を登録する際にカラーヒストグラムの計算結果を合わせて記憶するようにします。そして類似画像検索時にはカラーヒストグラムの近いものを探す、というアルゴリズムで実装できます。例えばこちらの画像(340 * 340)が上記2つの画像のどちらに似ているか、という識別をしてみます:
snooker


この画像のカラーヒストグラムはこのようになりました:
2017092002


簡単にいうと、このヒストグラムだけを比較して、「ヒストグラムはどの画像に近いか?」を判断することになります。もちろん画像のサイズは全て同じではないのでそこは正規化する必要もありますが、ロジックそのものはこれで実現できそうです。


もちろん「このロジックで精度の高い類似画像検索が実現できるか?」は別に考慮する必要があります。たとえば先程の上限逆さまにしたこの画像:
snooker


これを「元の画像と似ている」と判断すべきか、「似ていない」と判断すべきかはケース・バイ・ケースだと思っています(似ていると判断したいケースもあれば、似ていないと判断したいケースもある)。このカラーヒストグラムを使ったアルゴリズムの場合は回転結果は全く同じカラーヒストグラムを生成することになるので「似ている」と判断したい時に有効なアルゴリズムの1つと言えますが、「似ていない」と判断させたいのであれば輪郭などを元に判断するアルゴリズムを採用する必要がある、という意味です。

自前で類似画像検索を作成しようとしている人の参考になれば。