Iconfinder が著作権侵害を排除する方法、ハッシュ アルゴリズムが画像の複製を検出

Iconfinder が著作権侵害を排除する方法、ハッシュ アルゴリズムが画像の複製を検出

Iconfinder は、デザイナー、開発者、その他のクリエイティブ ワーカー向けに優れたアイコンを提供するアイコン検索エンジンです。現在 340,000 を超えるアイコンをホストしており、有料アイコン ライブラリとしては世界最大です。ユーザーは、Iconfinder の取引セクションでオリジナル作品をアップロードして販売することもできます。毎月、何千ものアイコンが、大量の海賊版画像とともに Iconfinder にアップロードされています。 Iconfinder のエンジニア Silviu Tantos は、この記事で著作権侵害を排除するための斬新で独創的な画像重複検出技術を提案しています。

今後数週間以内に、重複したアップロード アイコンを検出する機能を展開する予定です。たとえば、ユーザーがアイコンをダウンロードし、それをアップロードして収益を得ようとした場合(これは以前にも起こったことです)、当社のアプローチではアイコンがすでに存在するかどうかを検出し、アカウントを不正なものとしてフラグ付けすることができます。多数のファイルの中にファイルが既に存在するかどうかを検出する一般的な方法は、データセット内の各ファイルのハッシュ値を計算し、そのハッシュ値を配列ライブラリに保存することです。特定のファイルを検索する場合は、まずファイルのハッシュ値を計算し、次にデータベースでハッシュ値を検索します。

ハッシュアルゴリズムの選択

暗号ハッシュ アルゴリズムは、一般的に使用されるハッシュ アルゴリズムです。 MD5、 SHA1、SHA256などの標準ライブラリはどの言語にも存在し、単純な使用例には非常に効果的です。

たとえば、 Pythonでは、まずhashlibモジュールをインポートし、次に関数を呼び出して文字列またはファイルのハッシュ値を生成します。

  1. >>>ハッシュライブラリをインポートする
  2.    
  3. # 文字列のハッシュ値を計算します。
  4. >>> hashlib.md5( '素早い茶色のキツネは怠け者の犬を飛び越える' ).hexdigest()
  5. '9e107d9d372bb6826bd81d3542a419d6'  
  6.    
  7. # 画像ファイルをメモリに読み込み、そのハッシュ値を計算します。
  8. >>> image_file = open( 'data/cat_grumpy_orig.png' ).read()
  9. >>> hashlib.md5(image_file).hexdigest()
  10. '3e1f6e9f2689d59b9ed28bcdab73455f'  

このアルゴリズムは、改ざんされていないアップロードされたファイルに対しては非常に有効です。入力データにわずかな変更があった場合、暗号化ハッシュ アルゴリズムによって雪崩効果が発生し、新しいファイルのハッシュ値が元のファイルのハッシュ値と完全に異なるものになります。

たとえば、次の例では、文末にピリオドが追加されています。

  1. # 元のテキスト。
  2. >>> hashlib.md5( '素早い茶色のキツネは怠け者の犬を飛び越える' ).hexdigest()
  3. '9e107d9d372bb6826bd81d3542a419d6'  
  4.    
  5. # テキストを若干修正しました。
  6. >>> hashlib.md5( '素早い茶色のキツネは怠け者の犬を飛び越えます。' ).hexdigest()
  7. 'e4d909c290d0fb1ca068ffaddf22cbd0'  
画像の背景色が変更されたり、画像が切り取られたり、回転したり、単一のピクセルが変更されたりすると、画像ハッシュ ライブラリと一致しなくなります。従来のハッシュ アルゴリズムは実用的ではないことがわかります。上記の例でわかるように、ハッシュ値 9e107d9d372bb6826bd81d3542a419d6 と e4d909c290d0fb1ca068ffaddf22cbd0 はほとんど異なります(いくつかの文字を除く)。

たとえば、画像内の猫の鼻の色を変更すると、画像のハッシュ値が変わります。

オリジナル画像 修正画像

  1. # 元の画像をメモリに読み込み、そのハッシュ値を計算します。
  2. >>> image_file = open( 'data/cat_grumpy_orig.png' ).read()
  3. >>> hashlib.md5(image_file).hexdigest()
  4. '3e1f6e9f2689d59b9ed28bcdab73455f'  
  5.    
  6. # 変更されたイメージをメモリに読み込み、そのハッシュ値を計算します。
  7. >>> image_file_modified = open( 'data/cat_grumpy_modif.png' ).read()
  8. >>> hashlib.md5(image_file_modified).hexdigest()
  9. '12d1b9409c3e8e0361c24beaee9c0ab1'  

知覚ハッシュ アルゴリズムは数多く存在します。この論文では、隣接するピクセル間の輝度差を計算し、相対的な勾配を決定する新しい dhash (差分ハッシュ) アルゴリズムを提案します。上記のユースケースでは、知覚ハッシュが非常にうまく機能します。知覚ハッシュ アルゴリズムは、ファイル コンテンツのさまざまな特徴からマルチメディア ファイルのフィンガープリントを取得し、異なるファイル間の微妙な違いを柔軟に区別できます。

dハッシュ

dHash アルゴリズムについて詳しく説明する前に、まず基本的な知識をいくつか紹介します。カラー画像は RGB の 3 つの原色で構成されており、赤、緑、青の 3 つの原色の色セットとして見ることができます。たとえば、Python Imaging Library (PIL) を使用して画像を読み込み、ピクセル値を出力します。

テスト画像

  1. >>> PILから画像をインポート
  2. >>> test_image = Image.open( 'data/test_image.jpg' )
  3.    
  4. # 画像は 8x8 ピクセルの RGB 画像です。
  5. >>> '画像モード: %s'を印刷% test_image.mode
  6. 画像モード: RGB
  7. >>> print '幅: %s px、高さ: %s px' % (test_image.size[ 0 ]、test_image.size[ 1 ])
  8. 幅: 4ピクセル、高さ: 4ピクセル
  9.    
  10. # 画像からピクセル値を取得し、それに基づいて行に印刷します
  11. # 画像の幅。
  12. >>> 幅、高さ = test_image.size
  13. >>> ピクセル = リスト(test_image.getdata())
  14. >>> xrange(幅)内の列について:
  15. ...ピクセルを印刷[col:col+width]
  16. ...
  17. [( 255 , 0 , 0 ), ( 0 , 255 , 0 ), ( 0 , 0 , 255 ), ( 255 , 255 , 255 )]
  18. [( 0 , 0 , 0 ), ( 212 , 45 , 45 ), ( 51 , 92 , 154 ), ( 130 , 183 , 47 )]
  19. [( 206 , 210 , 198 ), ( 131 , 78 , 8 ), ( 131 , 156 , 180 ), ( 117 , 155 , 201 )]
  20. [( 104 , 133 , 170 ), ( 215 , 130 , 20 ), ( 153 , 155 , 155 ), ( 104 , 142 , 191 )]

さて、dHash アルゴリズムに戻りましょう。アルゴリズムには 4 つのステップがあります。この記事では、各ステップを詳しく説明し、元の画像と変更された画像への影響を検証します。最初の 3 つのピクセルの赤、緑、青のカラー強度値はそれぞれ 255 で、他の 2 つのピクセルのカラー強度値はそれぞれ 0 です。純粋な黒のピクセルの 3 つの原色は 0 で、純粋な白のピクセルの 3 つの原色は 255 です。その他の色のピクセルは、3 つの原色値の異なる強度で構成されます。

1. グレースケール画像

画像をグレースケール化すると、ピクセル値が光度値まで削減されます。たとえば、白いピクセル (255, 255, 255) は 255 になり、黒いピクセル (0,0,0) は 0 になります。

元の画像(手順 1 後) 変更後の画像(手順 1 後)

#p#

2. 画像を一般的なサイズに縮小する

画像を、幅と高さが 1 ピクセルの 9 x 8 ピクセルなどの共通の基本サイズに縮小します (このサイズである理由は手順 3 でわかります)。この方法では、画像から高周波と詳細が削除され、72 個の強度値を持つサンプルが生成されます。画像のサイズ変更や拡大を行ってもハッシュ値は変更されないため、すべての画像はこのサイズに正規化されます。

元の画像(手順2の後) 変更された画像(手順2の後)

3. 隣接するピクセルを比較する

最初の 2 つの手順が実行されると、強度値のリストが取得され、このバイナリ値配列の各行の隣接するピクセルが比較されます。

  1. >>> PILから画像をインポート
  2. >>> img = Image.open( 'data/cat_grumpy_orig_after_step_2.png' )
  3. >>> 幅、高さ = img.size
  4. >>> ピクセル = リスト(img.getdata())
  5. >>> xrange(幅)内の列について:
  6. ...ピクセルを印刷[col:col+width]
  7. ...
  8. [ 254 254 255 253 248 254 255 254 255 ]
  9. [ 254 255 253 248 254 255 254 255 255 ]
  10. [ 253 248 254 255 254 255 255 255 222 ]
  11. [ 248 254 255 254 255 255 255 222 184 ]
  12. [ 254 255 254 255 255 222 184 177 ]
  13. [ 255 254 255 255 222 184 177 184 ]
  14. [ 254 255 255 255 222 184 177 184 225 ]
  15. [ 255 255 255 222 184 177 184 225 255 ]

最初の値 254 は 2 番目の値 254 と比較され、2 番目の値は 3 番目の値と比較され、以下同様にして、行ごとに 8 つのブール値が生成されます。

  1. >>> 差 = []
  2. >>> xrange(height)内の行の場合:
  3. ... xrange(width) の col の場合:
  4. ... col != width の場合:
  5. ... 差を追加します(ピクセル[列+行] > ピクセル[(列+行)+ 1 ])
  6. ...
  7. >>> xrange(width - 1 )内のcolの場合:
  8. ... 差を印刷[col:col+(width- 1 )]
  9. ...
  10. [誤り、誤り、真、真、誤り、誤り、真、誤り]
  11. [誤り、真、真、誤り、誤り、真、誤り、誤り]
  12. [真、真、偽、偽、真、偽、偽、偽]
  13. [真、偽、偽、真、偽、偽、偽、真]
  14. [偽、偽、真、偽、偽、偽、真、真]
  15. [誤り、真、誤り、誤り、誤り、真、真、誤り]
  16. [真、偽、偽、偽、真、真、偽、偽]
  17. [偽、偽、偽、真、真、偽、偽、真]

4. バイナリに変換する

ハッシュ値の保存と使用を容易にするために、8 つのブール値は 16 進文字列に変換されます。 True は 1 になり、False は 0 になります。

Python実装

完全な Python で実装された完全なアルゴリズムは次のとおりです。

  1. def dhash(イメージ、hash_size = 8 ):
  2. # 画像を 1 ステップでグレースケール化して縮小します。
  3. 画像 = image.convert( 'L' ).resize(
  4. (ハッシュサイズ + 1 、ハッシュサイズ)、
  5. Image.ANTIALIAS、
  6.    
  7. ピクセル = リスト(image.getdata())
  8.    
  9. # 隣接するピクセルを比較します。
  10. 差 = []
  11.      xrange(hash_size) 内の行の場合:
  12.          xrange(hash_size)内の列の場合:
  13. ピクセル左 = image.getpixel((列、行))
  14. ピクセル右 = image.getpixel((列 + 1 、行))
  15. 差を追加します(pixel_left >pixel_right)
  16.    
  17. # バイナリ配列を 16 進文字列に変換します。
  18. 小数値 = 0  
  19. 16進文字列 = []
  20.     インデックス、enumerate(差異)の値:
  21.         の場合:
  22. 小数点値 += 2 **(インデックス % 8 )
  23.          (インデックス % 8 ) == 7 の場合:
  24. hex_string.append(hex(decimal_value)[ 2 :].rjust( 2 , '0' ))
  25. 小数値 = 0  
  26.    
  27.     戻る  '' .join(16進文字列)

最も一般的なケースでは、画像がわずかに異なる場合、ハッシュ値は同じになる可能性が高いため、直接比較できます。

  1. >>> PILから画像をインポート
  2. >>> ユーティリティからdhash、hamming_distanceをインポートします
  3. >>> orig = Image.open( 'data/cat_grumpy_orig.png' )
  4. >>> modif = Image.open( 'data/cat_grumpy_modif.png' )
  5. >>> dhash(原文)
  6. '4c8e3366c275650f'  
  7. >>> dhash(変更)
  8. '4c8e3366c275650f'  
  9. >>> dhash(orig) == dhash(modif)
  10. 真実

ハッシュ値を保存する SQL データベースがある場合は、ハッシュ値「4c8e3366c275650f」が存在するかどうかを簡単に判断できます。

  1. image_hashes から pk、hash、file_path を選択
  2. ここで、ハッシュ = '4c8e3366c275650f' ;

ここで、大きな違いがある画像ではハッシュ値が異なる場合があるため、ある文字列を別の文字列に置き換えるために必要な最小文字数、つまりハミング距離を計算する必要があります。

Wikipedia には、2 つの文字列間のハミング距離を計算する Python のサンプル コードがいくつか掲載されています。ただし、MySQL データベースの計算とクエリに基づいて直接実装することもできます。

  1. pk、ハッシュ、BIT_COUNT( を選択
  2. CONV(ハッシュ, 16 , 10 ) ^ CONV( '4c8e3366c275650f' , 16 , 10 )
  3. ) をハミング距離として
  4. image_hashesから
  5. ハミング距離 < 4 である 
  6. ハミング距離 ASC で並べ替えます。

クエリされた値とデータベース内のハッシュ値に対して XOR 演算を実行し、異なる桁の数をカウントします。 BIT_COUNT は整数に対してのみ動作できるため、すべての 16 進ハッシュ値は 10 進数に変換する必要があります。

結論

この記事では、紹介したアルゴリズムを実装するために Python を使用していますが、もちろん、読者は任意のプログラミング言語を使用してアルゴリズムを実装できます。

はじめに述べたように、この記事のアルゴリズムは、重複したアイコンの送信を防ぐために Iconfinder に適用されます。知覚ハッシュ アルゴリズムは、より実用的な用途を持つことが期待できます。類似した特徴を持つ画像は類似したハッシュ値を持つため、画像推奨システムが類似した画像を見つけるのに役立ちます。

オリジナルリンク: Silviu Tantos翻訳: Bole Online - Xiaoyu

翻訳リンク: http://blog.jobbole.com/65914/

<<:  靴下が山積みになっています。靴下をペアにするには、最も速くて効率的なアルゴリズムをどのように使用すればよいでしょうか?

>>:  顔認識アルゴリズムは人間の認識能力を超えている

ブログ    
ブログ    
ブログ    
ブログ    
ブログ    
ブログ    
ブログ    

推薦する

ソフトウェア開発を簡素化する 5 つの機械学習ツール

[51CTO.com クイック翻訳] 機械学習を使用する開発者の間での議論のほとんどは、AI ベース...

Raft アルゴリズムの原理と CMQ への応用 (パート 2)

CMQにおけるラフトの応用初期には、rabbitmqをベースにスケーラブルなメッセージミドルウェア...

...

CCTV 3.15は顔認識の悪用を暴露し、多くの教育企業が同様のカメラを使用する可能性がある

CCTV スクリーンショット街面の李婷が報告顔認識の応用シナリオはますます多様化しており、その背後...

誰が私たちの個人情報をスパイしているのでしょうか?顔認識の悪用

「顔認証」や「顔スキャン決済」は顔認識技術の継続的な発展です。今では、小型カメラの助けを借りて、私た...

プログラマーは「自殺」している。人工知能が進化し続ける中、人間は何をすべきか?

中国、日本、韓国の囲碁名人数十人がこのゲームに挑み、アルファ碁は1敗もせずに60連勝した。その後、世...

...

注目を浴びた分析と AI の 5 つの大惨事

データと機械学習アルゴリズムによって生成される洞察は非常に貴重ですが、間違いはあなたの評判、収益、さ...

...

量子人工知能研究における課題と機会

量子コンピューティングと人工知能の融合により、大きな期待と可能性を秘めた研究の最前線である量子人工知...

父親が8歳の娘にディープラーニングを説明する:11の事実

「ニューラル ネットワークは数を数えるのと同じくらい簡単です」、「畳み込み層は単なるバット シグナル...

テレンス・タオ:私の数学的経験に基づくと、室温超伝導LK-99とその再現は非常に刺激的です

昨今、室温超伝導の再現に対する世界的な熱気は衰えを知らず、さまざまな有力者が自らの見解を表明している...

アディダスのロボット工場で作られた靴が出荷されようとしている

アディダスがドイツに開設したロボット靴製造工場「スピードファクトリー」が正式に生産を開始したと報じら...

...

...