質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

4381閲覧

離散コサイン変換とimagehashについて

r3y2u1

総合スコア14

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

2クリップ

投稿2017/08/28 13:32

編集2017/08/28 16:10

python

1コード 2def phash(image, hash_size=8, highfreq_factor=4): 3 """ 4 Perceptual Hash computation. 5 6 Implementation follows http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html 7 8 @image must be a PIL instance. 9 """ 10 import scipy.fftpack 11 img_size = hash_size * highfreq_factor 12 image = image.convert("L").resize((img_size, img_size), Image.ANTIALIAS) 13 pixels = numpy.array(image.getdata(), dtype=numpy.float).reshape((img_size, img_size)) 14 dct = scipy.fftpack.dct(scipy.fftpack.dct(pixels, axis=0), axis=1) 15 dctlowfreq = dct[:hash_size, :hash_size] 16 med = numpy.median(dctlowfreq) 17 diff = dctlowfreq > med 18 return ImageHash(diff) 19 20```以前もimagehashについて質問したのですが、 21・なぜ離散コサイン変換を使うとガンマ補正やヒストグラム補正がかかっている画像でも似たような画像と認識できるのか(Average hash)では異なる画像と認識されてしまうのか 22 23・Average hashでは8x8に縮小していたのにphashでは32×32に縮小していました。DCTを行うには良い大きさらしいですがそれは何故ですか? 24 25・imagehashのphashのアルゴリズム5.の平均値を計算するという所で、『最初の項は除去する』と書いてあるのですがそれはどういうことなのでしょうか?最初の行だけという意味で合ってますかね?
退会済みユーザー👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

・なぜ離散コサイン変換を使うとガンマ補正やヒストグラム補正がかかっている画像でも似たような画像と認識できるのか(Average hash)では異なる画像と認識されてしまうのか

average_hashでは文字通りピクセル平均値(mean())を基準値に用いるため、ガンマ補正やヒストグラム補正などの画面全体のピクセル値分布を歪める操作に対してロバストでない、つまりそのような操作によってハッシュ値が大きく変化してしまいます。

一方のphashでは、離散コサイン変換(DCT)によって得られる係数値の中央値(median)を基準値として用います。

DCTを理解している前提での説明:ガンマ補正やヒストグラム補正といった全体的なピクセル値操作をおこなっても、画像データが持つ空間的な構造/情報は維持されるため、DCT係数の大部分を占めるAC係数の分布はあまり変化しません。(※:詳細後述しますが、このPython実装には問題があるように思えます)

DCTをかなり乱暴に説明すると、1次元8点DCTは「1個の平均値(直流成分;DC)」+「7個のデータ"詳細度"=周波数別に分解された値(交流成分;AC)」への変換です。画像は2次元データですからそれぞれ縦/方向に適用すると2次元8x8点DCTとなり、「1個の平均値(DC)」+「63個のAC値」となります。ガンマ補正やヒストグラム補正はピクセル値を一律で変化させるためDC値に強く影響しますが、AC値はデータがもっている空間的な構造情報(=周波数)に対応するため、そのような変換では値が変化しずらいという性質があります。


・Average hashでは8x8に縮小していたのにphashでは32×32に縮小していました。DCTを行うには良い大きさらしいですがそれは何故ですか?

ドキュメントの誤読です。DCT処理にとって好都合というわけではなく、32x32DCT係数のうち低周波数側8x8個の係数だけを拾ってくると、画像の低周波情報=おおまかな空間構造をバランスよく捉えられると言っています。なおDCTの計算都合だけでいえば、2のベキ乗ならばOKです。


・imagehashのphashのアルゴリズム5.の平均値を計算するという所で、『最初の項は除去する』と書いてあるのですがそれはどういうことなのでしょうか?

DCT係数のDC成分を除去するのが目的です。計算式上、最初の項はDC成分係数になります。

最初の行だけという意味で合ってますかね?

オリジナルのpHash実装では、2次元DCT係数の 第1行目および第1列目をすべて除去 しているようです。一方、Python imagehashのphashではこの処理を 全く適用しておらず、DC係数も含めてハッシュ計算を行なっています。本来のアルゴリズム意図からすれば、imagehash実装が誤っているようにも思えます。

投稿2017/08/28 15:45

編集2017/08/29 04:42
yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

r3y2u1

2017/08/28 16:19

yohhoyさん回答ありがとうございます。 imagehashのphashでは除去する処理を行っていないのですね。 dctlowfreq = dct[1:9, 1:9] このようにphashのプログラムを変更したらオリジナルのphashと同じになると思うのですがどうでしょうか?
yohhoy

2017/08/29 04:45

利用するDCT係数の範囲は、オリジナルpHash実装と同一になります。 オリジナル実装との厳密一致が必要ならば、係数並び順も確認されたほうが良いです。なお、アルゴリズム上はハミング距離を用いて類似判定をおこなうため、並び順にさえ一貫性があれば具体的な並び順そのものは不問となっています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問