だから人間は大嫌いだ!!

ゲームプログラミングとか、気になるWebのサービスのこととか

多次元ヒストグラムを使って重複画像を発見する「多次元よめ比較マシーン」とは?

人間の中には、ネットを徘徊して、二次元画像(よめ)を拾ってフォルダに保存するという、二次元画像(よめ)収集マシーンみたいなのがいるらしいですね。いや、彼らは普段は「普通の人ですから」みたいな顔していることが多いから、バレていないかもしれない。

PixivとかGoogle画像(よめ)検索なんかを駆使して、淡々と収集するわけですよ。俺妹が流行っている時期とか、ひたすら何千枚と「黒猫」フォルダに二次元画像(よめ)を詰め込み、ラブライブが流行ると「おれのニコ」フォルダを作って、もりもりと画像(よめ)を詰め込む。病院に行く一歩手前な人間さんたち。

でね、私は彼らを見ていて思うのです。そこまでやるようなプロフェッショナルでも、ありえないミスを犯すものだなぁと。人間って、所詮は欠陥だらけのいきものなんだぁと。人間は、すでに収集済みの二次元画像(よめ)を、気が付かずにもう一度収集してしまうなんてことを平気でやらかしちゃうんだなぁと。

ほんとね、ありえない。嫁の顔覚えてないとか、まじでありえなえい。おまえの画像(よめ)への愛情はその程度なのかと、フォルダの画像(よめ)が泣いているぞと言いたい。5分ぐらいは言いたい。

どうしたら画像(よめ)が収集済みかわかるようになるん?

熱心な画像(よめ)収集家にもなると、何千もの画像(よめ)ファイルの中身をいちいち確認して、かぶっていないかを確認するなんてできない。だから、コンピューターに任せたいと思うわけですよね。しかし、コンピューターは「全く同じ」を判別はできても、「だいたい同じ」を見分けるのが難しい。ファイルの中を開いて比較すればいいだけじゃね?っと思われがちだけど、インターネットという世界はそこまで甘くない。

ネット上の画像(よめ)ファイルは、アップロード先の仕組みによって、ファイルフォーマットを変えられたりとか、画像(よめ)の大きさを変えられたりとかする。JPGみたいなものだと、ふにゃふにゃになるぐらい画像(よめ)を圧縮することもある。つまり何が言いたいかと言うと、画像(よめ)というのは、一度でもネット上に出回ると、だいたいは劣化コピーみたい状態でぶくぶく広がっていくのです。そんなんじゃ、だいたい似ているを見分けるのが苦手なコンピューターには、判別が難しいのですよ。

f:id:sakura_q:20150204000645j:plain

じゃあ、どうしたらいいのか?通常はOpenCVを使って、もにょもにょっとするのが一般的なんだけど、これがまた意外と面倒だったりする。画像(よめ)収集家の多くは、プロフェッショナルとか言いつつも、その実態は自宅の警備なんかも請け負う方が多いので、作業は常に自宅。ごっついサーバなんて持っていないし、そんなお金は無い。手軽にやらせてくれよ、なんて思ったりするわけです。

そこで、単純な二次元画像の比較をシンプルに行える多次元ヒストグラム(Histogram method)を実装した「多次元よめ比較マシーン」を作ってみたのです。実際に作ったのは結構昔なんだけど、「ぼくがつくったさいきょうぷろぐらむふぉるだー」の中でほこりをかぶっていたので、発掘してうpってみた。せっかくだから、紹介しようと思う。

「多次元よめ比較マシーン」の使い方

1. Perlを動くようにする

Perlという言語で作ったスクリプトファイルなので、こいつが動くようにセットアップが必要。MacとかLinuxユーザなら最初からインストールされているけど、Windowsなんて使っていようものならここから落としてきてインストールせんといかん。そういう説明は面倒だから、ぐーぐるに聞いてほしい。

2. Image::Magickをインストールする

「Image::Magick」っていうPerlのモジュールをインストールしないといかんので、黒い画面で以下のコマンドを入力。

$ cpan Image::Magick

えっ?黒い画面がわからない?ぐーぐるや!ぐーぐる先生を召喚するんや!

3. いざ、実行や!

Githubのページ(https://github.com/qkwkw/SimpleColorBuckets)からファイルをダウンロードして、「findYome.pl」を画像(よめ)が置いてあるフォルダに入れる。それでもって、比較したいファイルを、「findYome.pl」にドラッグアンドドロップ

f:id:sakura_q:20150204001818j:plain

もちろん、黒い画面で入力してもいい。

$ ./findYome.pl target.png

すると…

$ ./findYome.pl target.jpg
089.9%,target-samb.jpg
  found 1 file(s).
  Press enter key to finish :

こんなかんじで、一致率が高いファイルが表示される。あと、どれぐらい似ているのかも%(パーセント)単位で出てくるじゃありませんか。ちなみにデフォルトだと、70%以上一致しているのが出力されるのです。

この%(パーセント)って、どうやって算出してるん?

多次元ヒストグラム(Histogram method)というアルゴリズムを使ってる。やりかたはとてもシンプル。画像(よめ)ファイルの内容を一定の解像度、例えば400x400ピクセルに強引に変更して、各ピクセルの情報量を圧縮して「ヒストグラム・データ」というのを作る。で、画像(よめ)ファイルのヒストグラム・データの内容がどの程度一致しているのかを比較して、%(パーセント)という単位でスコア化されるようになっているわけですよ。けっこう、有名なアルゴリズムなんですけどね。

ただね、こういう原始って感じがするアルゴリズムは往々にして、精度が低くてチューニングも面倒と決まっているの。だから必ずと言っていいほど、一手間必要になるのですよ。で、この多次元よめ比較マシーンでは、画像(よめ)ファイルを解像度別でいくつか用意して比較することで、精度が上がるようにしたのです。

それでも、漫画のページみたいな白黒かつ線ばかりものものは誤検出がすごく多い。どうしても、そういう面倒な画像(よめ)ファイルを正確に抽出したいというのなら、解像度を大きくして比較するようfindYome.plのパラメーターを調整するか、OpenCVに頼らなくちゃいけない。

できれば大規模なWebアプリで使いたいのだけど?

このツールはもともと、サーバ上で実行するために作られたものだった(そもそも、こんな用途で使うのが目的じゃなくもっと社会的に意義のあることに使っていたわけでして…)。その時は、画像(よめ)を判別するための「ヒストグラム・データ」を、あらかじめデータベースに登録して判別するようにしていたのです。ただまぁ、インメモリでできそうなことをわざわざファイルでやっていたり、そもそもバイナリ的な処理をあんまり有効活用していなかったりで、パフォーマンスはそこまで良くないんですよね。

もっとそもそもな話。多次元ヒストグラム(Histogram method)はあんまりパフォーマンスが良くないので、リアルタイムやオンライン系には向かないんです。ハイパフォーマンスが求められるというなら、素直にOpenCVを使えばいいと思う。

いや、それが面倒なんだけど?

うるせー、わがまま言うなら使うなよ!(怒`皿´)無理なものは無理なんだよっ!

本来なら、局所特徴量ってのを計測するのがイマドキっぽいやり方なのだけれど、二次元って時点でそこまで気にするところじゃないだろうと、端折っていたりもするのですよ。ほんとね、いい加減な方だとおもうのですよ。シンプルにやりたい人に向けて作ったので、あんまりユースケースを広げられたら困るのです。

これだからもう、人間は大嫌いだ。あーあ、やる気ぜろになった。もう、かき氷食ってふて寝してやる。