web-dev-qa-db-ja.com

(純粋な)PHP / MySQLで類似の画像を検索する

私のユーザーは私のウェブサイトに画像をアップロードしています。最初に、アップロード済みの画像を最初に提供したいと思います。私の考えは、1。既存のすべての画像のある種の画像「ハッシュ」を作成することです。2。新しくアップロードされた画像のハッシュを作成し、データベース内の他の画像と比較します。

http://www.pureftpd.org/project/libpuzzle または http://phash.org/ などのような興味深い解決策をいくつか見つけましたが、それらは1つあります。以上の問題

  1. PHP(またはPHP)にはない)への非標準の拡張が必要です-私にとっては問題ありませんが、次のように作成したいと思います私の人気のあるCMSへのプラグイン。これは、私の制御なしに多くのホスティング環境で使用されています。
  2. 彼らは2つの画像を比較していますが、私は1対多(たとえば数千)を比較する必要があり、1つずつそれを行うことは非常に効果がない/遅いです... ...

非常に類似した画像のみを見つけても問題ありません(たとえば、サイズが異なる、jpgが再保存されている、jpgの圧縮率が異なるなど)。

私が得た唯一のアイデアは、画像のサイズをたとえば次のように変更することです。 5px * 5px * 256色、それの文字列表現を作成し、同じものを見つけます。しかし、サイズの異なる同じ画像が2つしかない場合でも、色にわずかな違いが生じる可能性があるため、100%同じ画像を見つけるだけでは意味がありません。

したがって、画像の文字列表現の適切な形式が必要になります。これは、SQL関数で使用して、類似した方法やその他の優れた方法を見つけるために使用できます。例えば。 phashは知覚ハッシュを作成するため、2つの数値が近い場合、画像も近くなるはずなので、最も近い距離を見つける必要があります。しかし、これも外部ライブラリです。

簡単な方法はありますか?

22
Tomáš Kapler

私はこれを経験しました正確以前に同じ問題がありました。

私がしたことを自由にコピーしてください、そしてうまくいけばそれはあなた/あなたの問題を解決するのに役立つでしょう。


どうやって解決したか

あなたが考えているのと同じように、失敗した私の最初のアイデアは、(サイズに関係なく)すべての画像に対して文字列を作成することになったということです。しかし、私はすぐにこれがあなたのデータベースを非常に速くいっぱいにすることを理解しました、そして効果的ではありませんでした。

次のオプション(機能する)は、より小さな画像(5pxのアイデアなど)でした。私はまさにそれを実行しましたが、10px * 10px画像を使用しました。各画像の「ハッシュ」を作成する方法は、imagecolorat()関数でした。

ここでphp.netを参照してください。

画像のrgb色を受け取ったとき、色があまり具体的でないように、最も近い50に丸めました。その数(50)は、検索の方法に応じて変更する必要がありますspecific

例:

// Pixel RGB
rgb(105, 126, 225) // Original
rgb(100, 150, 250) // After rounding numbers to nearest 50

すべてのピクセルに対してこれを行った後(10px * 10pxは100rgb()を返します)、次にそれらを配列に変換し、base64_encode()およびserialize()

類似の画像を検索するときは、アップロードしたい画像に対してまったく同じプロセスを実行し、データベースから画像の「ハッシュ」を抽出してすべてを比較し、一致する丸められたrgbを確認しました。


チップ

  • 大きい50rgbの丸めに含まれている場合、あまり具体的ではない検索が行われます(またはその逆)。

  • [〜#〜] sql [〜#〜]をより具体的にしたい場合は、画像に関する情報をデータベースに保存する方がよい場合がありますextra/Specific 、データベースで取得する検索を制限できるようにします。 eg。アスペクト比が4:3の場合、データベースから4:3周辺の画像のみをプルします。 (等)

  • これを完全に取得するのは難しい場合があります5px * 5pxなので、提案は phpthumb です。私はそれを次の構文で使用しました:

phpthumb.php?src=IMAGE_NAME_HERE.png&w=10&h=10&zc=1
// &w=  width of your image
// &h=  height of your image
// &zc= zoom control. 0:Keep aspect ratio, 1:Change to suit your width+height

幸運の仲間、私が助けることができることを願っています。

23
jay

簡単なphp実装については、以下を確認してください: https://github.com/kennethrapp/phasher

ただし、「比較」用のネイティブmySql関数があるかどうか疑問に思います(上記のphpクラスを参照)

2
sebilasse

画像を8x8に縮小してから、RGBを1バイトのHSVに変換して、結果のハッシュが172バイトの文字列になるようにします。

HSVHSVHSVHSVHSVHSVHSVHSV... (from 8x8 block, 172 bytes long)
0fff0f3ffff4373f346fff00...

100%正確ではありませんが(一部の重複は見つかりません)、正常に機能し、誤検知の結果がないように見えます。

0
Peter

学術的な方法でそれを置くと、あなたが探しているのは、2つの画像を取り込んで、2つの画像がどれだけ離れているか/類似しているかの指標を返す類似性関数です。このインジケータは、-1から1(遠く離れているか非常に近い)の範囲の10進数である可能性があります。この機能を使用すると、画像を参照として設定し、すべての画像をそれと比較できます。次に、類似した画像を見つけるのは、MySQLのようなRDBMS内のダブルフィールドを単純に検索するだけで、それに最も近い類似性係数を見つけるのと同じくらい簡単です。

残っているのは、相似関数を定義する方法だけです。正直なところ、これは特定の問題です。それはあなたが似ていると呼ぶものに依存します。しかし、 共分散 は通常、良い出発点です。2つの画像が同じサイズである必要があるだけで、大したことではないと思います。それでも、「2つの画像間の類似性の尺度」を検索する他の多くのアイデアを見つけることができます。

0
Mehran