2枚の画像を比較するアルゴリズム(C#)
2023-09-04 10:06:11
質問
私はC#で重複した画像を見つけるためのツールを書いています。現在、私はファイルのMD5チェックサムを作成し、それらを比較します。
残念なことに、画像は
- 90 度回転させたもの。
- 異なる寸法を持つ(同じ内容でより小さな画像)。
- 圧縮またはファイル タイプが異なる (例: JPEG アーティファクト。下記を参照)。
この問題を解決するためには、どのようなアプローチが良いでしょうか?
どのように解決するのですか?
256ビット(MD5は128ビット)の画像ハッシュを使った簡単な方法を紹介します。
- 画像のサイズを 16x16 ピクセル
- に色を減らす。 黒 / 白 (これは 真 / false このコンソール出力では)
-
にブール値を読み込む。
List<bool>
- これはハッシュです。
コード :
public static List<bool> GetHash(Bitmap bmpSource)
{
List<bool> lResult = new List<bool>();
//create new image with 16x16 pixel
Bitmap bmpMin = new Bitmap(bmpSource, new Size(16, 16));
for (int j = 0; j < bmpMin.Height; j++)
{
for (int i = 0; i < bmpMin.Width; i++)
{
//reduce colors to true / false
lResult.Add(bmpMin.GetPixel(i, j).GetBrightness() < 0.5f);
}
}
return lResult;
}
知っている
GetPixel
はそれほど高速ではありませんが、16x16 ピクセルの画像ではボトルネックになることはないはずです。
- このハッシュを他の画像のハッシュ値と比較し、許容誤差を追加します (他のハッシュと異なる可能性のあるピクセル数)。
コードです。
List<bool> iHash1 = GetHash(new Bitmap(@"C:\mykoala1.jpg"));
List<bool> iHash2 = GetHash(new Bitmap(@"C:\mykoala2.jpg"));
//determine the number of equal pixel (x of 256)
int equalElements = iHash1.Zip(iHash2, (i, j) => i == j).Count(eq => eq);
ということで、このコードは等しい画像を見つけることができます。
- 異なるファイル形式 (例: jpg, png, bmp)
-
回転 (90, 180, 270), 水平・垂直反転 - これは
i
とj
- 異なる寸法(同じアスペクトであることが必要)
- 異なる圧縮 (jpeg アーチファクトのような品質低下の場合、許容範囲が必要) - 99% の等質性を同じ画像とし、50% を異なる画像として受け入れることができます。
- 色がガイスケーリングに変更され、その逆も可能 (明るさは色に依存しないため)
更新・改善。
この方法をしばらく使ってみて、いくつかの改善点に気づきました。
-
を置き換える
GetPixel
より高いパフォーマンスのために - を使用して exeif-thumbnail を使用することで、画像全体を読み込む代わりにパフォーマンスを向上させることができます。
-
を設定する代わりに
0.5f
を設定して明暗を区別するのではなく、256ピクセルすべての明度の中央値を使用します。そうしないと、暗い画像と明るい画像が同じであると見なされ、明るさが変化した画像を検出することができます。 -
が必要な場合は
はやい
の計算が必要な場合は
bool[]
またはList<bool>
メモリを節約する必要があり、多くのハッシュを保存する必要がある場合はBitarray
というのも、ブール値はビット単位で保存されるのではなく バイト !
関連
-
[解決済み】C#でクエスチョンマークを2つ並べるとどんな意味になるのか?
-
[解決済み】指定されたキャストが有効でない?
-
[解決済み】C# ASP.NET使用時に「WebClientのリクエスト中に例外が発生しました。
-
[解決済み】非静的メソッドはターゲットを必要とする
-
[解決済み】2年前のMSDateを把握する【クローズド
-
[解決済み】別のスレッドがこのオブジェクトを所有しているため、呼び出し側のスレッドはこのオブジェクトにアクセスできない
-
[解決済み] AndroidのListViewで画像を遅延ロードする方法
-
[解決済み] 2つの日付の差(日数)を計算する?
-
[解決済み] HTMLでBase64画像を表示する方法
-
[解決済み] LINQ集計アルゴリズム説明
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】「未割り当てのローカル変数を使用」とはどういう意味ですか?
-
[解決済み】ここで「要求URIに一致するHTTPリソースが見つかりませんでした」となるのはなぜですか?
-
[解決済み】"The ConnectionString property has not been initialized "を修正する方法
-
[解決済み】ソケットのアドレス(プロトコル/ネットワークアドレス/ポート)は、通常1つしか使用できない?
-
[解決済み】Visual Studio: 操作を完了できませんでした。パラメータが正しくありません
-
[解決済み】WSACancelBlockingCallの例外について
-
[解決済み】2つ(またはそれ以上)のリストを1つに統合する(C# .NETで
-
[解決済み] ...基礎となる接続は閉じられました。予期しないエラーが受信で発生しました
-
[解決済み】データが存在しないのに読み込もうとする試みが無効である
-
[解決済み] 画像比較 - 高速アルゴリズム