Traditional Culture Encyclopedia - Traditional stories - C# grayscale images to find the most similar images by similarity algorithm

C# grayscale images to find the most similar images by similarity algorithm

This kind of image search can be done using a perceptual hash algorithm,

Step 1 Reduce the size of the image

Reduce the size of the image to 8x8, a total of ****64 pixels. The purpose of this step is to remove the differences between the various image sizes and image proportions, and retain only the basic information such as structure, light and dark.

Step 2 Convert to grayscale

The reduced image is converted to 64 levels of grayscale.

Step 3 Calculate the average gray value

Calculate the average gray value of all the pixels in the image

Step 4 Compare pixel grayscale

Compare each pixel's grayscale with the average, if it is greater than or equal to the average it is recorded as 1, if it is less than the average it is recorded as 0.

Step 5 Calculate the hash value

Combine the results of the previous step.

Combine the results of the previous step to form a 64-bit binary integer, which is the fingerprint of the image.

Step 6 Compare image fingerprints

Once you have the fingerprints of the images, you can compare the fingerprints of the different images to find out how many of the 64 bits are different. If the number of different bits is less than 5, the two images are similar, if it is more than 10, they are two different images.

The exact c# code can be found at

using?System;

using?System.IO;

using?System.Drawing;

namespace?SimilarPhoto

{

class?SimilarPhoto

{

Image?SourceImg;

public?SimilarPhoto(string?filePath)

{

SourceImg?=? Image.FromFile(filePath);

}

public?SimilarPhoto(Stream?stream)

{

SourceImg?=?Image.FromStream(stream);

}

public?String?GetHash()

{

Image?image?=?ReduceSize();

Byte[]?grayValues?=?ReduceColor(image);

Byte?average?=?CalcAverage(grayValues);

String?reslut?=?ComputeBits(grayValues,?average);

return?reslut;

}

//?Step?1?:?Reduce?size?to?8*8

private?Image?ReduceSize(int?width?=?8,?int?height?=?8)

{

Image?image ?=?SourceImg.GetThumbnailImage(width,?height,? ()? =>? {?return?false;?} ,?IntPtr.Zero);

return?image;

}

//?Step?2?:?Reduce?Color

private?Byte[]?ReduceColor(Image?image)

{

Bitmap?bitMap?=?new?Bitmap(image);

Byte[]?grayValues?=?new?Byte[image.Width?*?image.Height];

for(int?x?=? 0;?x<image.Width;?x++)

for(int?y?=?0;?y?<?image.Height;?y++)

{

Color?color?=?bitMap.GetPixel(x,?y);

byte?grayValue?=? (byte)((color.R?*?30?+?color.G?*?59?+?color.B?*?11)? /?100);

grayValues[x?*?image.Width?+?y]? =?grayValue;

}

return?grayValues;

}

//?Step?3?:?Average?the?colors

private?Byte?CalcAverage(byte []?values)

{

int?sum?=?0;

for?(int?i?=?0;?i?<?values.Length;?i++)

sum?+=? (int)values[i];

return?Convert.ToByte(sum?/?values.Length);

}

/?Step?4?:?Compute?the?bits

private? String?ComputeBits(byte[]?values,?byte?averageValue)

{

char[]?result?=?new?char[values.Length];

for?(int?i?=?0;? i?<?values.Length;?i++)

{

if?(values[i]? <?averageValue)

result[i]? =?' 0';

else

result[i]? =?' 1';

}

return?new?String(result);

}

//?Compare?hash

public?static?Int32?CalcSimilarDegree(string? a,?string?b)

{

if?(a.Length?! =?b.Length)

throw?new?ArgumentException();

int?count?=?0;

for?(int?i?=?0;?i?<?a.Length;?i++)

{

if ?(a[i]?! =?b[i])

count++;

}

return?count;

}

}

}

}

}