-
동일한 이미지를 빠르게 식별하는 알고리즘 feat.c# code프로그램(C# etc.) 2023. 2. 28. 09:39
동일한 이미지를 빠르게 식별하는 데 사용할 수 있는 다양한 알고리즘이 있습니다. 일반적으로 사용되는 알고리즘 중 하나는 Perceptual Hashing 알고리즘입니다. 작동 방식은 다음과 같습니다.
- 이미지 크기를 고정된 작은 크기(예: 8x8픽셀)로 조정합니다.
- 이미지를 회색조로 변환합니다.
- 각 이미지의 픽셀에 이산 코사인 변환(DCT)을 적용합니다. DCT는 공간 도메인의 픽셀 값을 주파수 도메인으로 변환합니다.
- 각 이미지에 대한 DCT 계수의 평균값을 계산합니다. 이 값은 계수 임계값에 사용됩니다. 계수가 평균보다 크면 1로 설정됩니다. 그렇지 않으면 0으로 설정됩니다.
- 임계값 계수를 단일 이진 문자열로 연결합니다. 이 문자열은 이미지의 지각 해시입니다.
- 해밍 거리 메트릭을 사용하여 두 이미지의 지각 해시를 비교합니다. 해밍 거리는 두 이진 문자열 간에 다른 비트 수입니다. 해밍 거리가 특정 임계값 미만이면 이미지가 동일한 것으로 간주됩니다.
이 알고리즘은 이미지당 적은 양의 계산만 필요하기 때문에 빠르고 결과적인 지각 해시는 콤팩트합니다. 그리고 비교하기 쉽습니다. 그러나 완벽하지 않으며 경우에 따라(예: 이미지 크기가 크게 조정되거나 압축된 경우) 모든 동일한 이미지를 식별하지 못할 수 있습니다.
Q2. 위 알고리즘을 c#코드로 보여줘
using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.Linq; public static class ImageHelper { public static byte[] GetPerceptualHash(Bitmap bitmap) { const int Size = 8; // Resize the image to a fixed size Bitmap resized = new Bitmap(bitmap, new Size(Size, Size)); // Convert the image to grayscale Bitmap gray = ToGrayscale(resized); // Apply DCT to the pixel values double[,] dct = DCT2D(gray); // Threshold the DCT coefficients double mean = Mean(dct); bool[] bits = Threshold(dct, mean); // Convert the bits to bytes byte[] bytes = BitsToBytes(bits); return bytes; } private static Bitmap ToGrayscale(Bitmap bitmap) { Bitmap gray = new Bitmap(bitmap.Width, bitmap.Height); for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { Color color = bitmap.GetPixel(x, y); byte grayValue = (byte)(0.299 * color.R + 0.587 * color.G + 0.114 * color.B); gray.SetPixel(x, y, Color.FromArgb(grayValue, grayValue, grayValue)); } } return gray; } private static double[,] DCT2D(Bitmap bitmap) { double[,] dct = new double[bitmap.Height, bitmap.Width]; for (int v = 0; v < bitmap.Height; v++) { for (int u = 0; u < bitmap.Width; u++) { double sum = 0.0; for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { Color color = bitmap.GetPixel(x, y); double grayValue = (0.299 * color.R + 0.587 * color.G + 0.114 * color.B) - 128; double cu = (u == 0) ? 1 / Math.Sqrt(2) : 1; double cv = (v == 0) ? 1 / Math.Sqrt(2) : 1; double cosU = Math.Cos(((2 * x + 1) * u * Math.PI) / (2 * bitmap.Width)); double cosV = Math.Cos(((2 * y + 1) * v * Math.PI) / (2 * bitmap.Height)); double value = cu * cv * grayValue * cosU * cosV; sum += value; } } double alpha = (u == 0) ? 1 / Math.Sqrt(bitmap.Width) : Math.Sqrt(2) / Math.Sqrt(bitmap.Width); double beta = (v == 0) ? 1 / Math.Sqrt(bitmap.Height) : Math.Sqrt(2) / Math.Sqrt(bitmap.Height); dct[v, u] = alpha * beta * sum; } } return dct; } private static double Mean(double[,] dct) { double sum = 0.0; for (int y = 0; y < dct.GetLength(0); y++) { for (int x = 0; x < dct.GetLength(1); x++) { sum += dct[y, x]; } } return sum / (dct.GetLength(0) * dct.GetLength(1)); } private static bool[] Threshold(double[,] dct, double threshold) { bool[] bits = new bool[dct.GetLength(0) * dct.GetLength(1)]; for (int y = 0; y < dct.GetLength(0); y++) { for (int x = 0; x < dct.GetLength(1); x++) { bits[y * dct.GetLength(1) + x] = (dct[y, x] > threshold); } } return bits; } private static byte[] BitsToBytes(bool[] bits) { byte[] bytes = new byte[bits.Length / 8]; for (int i = 0; i < bytes.Length; i++) { byte value = 0; for (int j = 0; j < 8; j++) { if (bits[i * 8 + j]) { value |= (byte)(1 << (7 - j)); } } bytes[i] = value; } return bytes; } public static int HammingDistance(byte[] hash1, byte[] hash2) { int distance = 0; for (int i = 0; i < hash1.Length; i++) { byte xor = (byte)(hash1[i] ^ hash2[i]); for (int j = 0; j < 8; j++) { if ((xor & (1 << (7 - j))) != 0) { distance++; } } } return distance; } }
Q2. 위 코드 사용해서 jpg파일 2개 비교하는 함수 보여줘
using System; using System.Drawing; using System.IO; public static class ImageComparison { public static bool AreImagesIdentical(string filePath1, string filePath2, int maxHammingDistance) { // Load the images from the files Bitmap bitmap1 = new Bitmap(filePath1); Bitmap bitmap2 = new Bitmap(filePath2); // Compute the perceptual hashes of the images byte[] hash1 = ImageHelper.GetPerceptualHash(bitmap1); byte[] hash2 = ImageHelper.GetPerceptualHash(bitmap2); // Compute the Hamming distance between the hashes int distance = ImageHelper.HammingDistance(hash1, hash2); // Compare the Hamming distance to the threshold return (distance <= maxHammingDistance); } }
'프로그램(C# etc.)' 카테고리의 다른 글
큰 이미지에서 작은 이미지 좌표를 찾는 빠른 알고리즘을 알려줘 feat.c# code (0) 2023.02.28 c# 프로그램이 시작하자마자 button1_Click 자동으로 호출하게 할 수 있어? (0) 2023.02.28 _ConnectionPtr 이 뭔지 알아? (0) 2023.02.10 c#에서 chrome.exe --remote-debugging-port=9222 --user-data-dir="c:/ChromeTEMP" CMD명령 하도록 코드 보여줘 (0) 2023.02.03 창최소화 이벤트 코드 (0) 2023.01.16