C# C语言中两幅图像的比较算法#
我正在用C#编写一个工具来查找重复的图像。目前,我创建了文件的MD5校验和,并比较了它们 不幸的是,图像可能是:C# C语言中两幅图像的比较算法#,c#,image,hash,C#,Image,Hash,我正在用C#编写一个工具来查找重复的图像。目前,我创建了文件的MD5校验和,并比较了它们 不幸的是,图像可能是: 旋转90度 具有不同的尺寸(具有相同内容的较小图像) 具有不同的压缩或文件类型(例如jpeg瑕疵,见下文) 解决此问题的最佳方法是什么?下面是一个使用256位图像哈希的简单方法(MD5有128位) 将图片大小调整为16x16像素 将颜色减少为黑色/白色(此控制台输出中等于真/假) 将布尔值读入列表——这是散列 代码: public static List<bool&g
- 旋转90度
- 具有不同的尺寸(具有相同内容的较小图像)
- 具有不同的压缩或文件类型(例如jpeg瑕疵,见下文)
解决此问题的最佳方法是什么?下面是一个使用256位图像哈希的简单方法(MD5有128位)
列表
——这是散列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;
}
因此,此代码能够找到具有以下功能的相同图像:
- 不同的文件格式(例如jpg、png、bmp)
- 旋转(90、180、270),水平/垂直翻转-通过改变
和i
j
- 不同的尺寸(需要相同的外观)
- 不同的压缩(在质量损失(如jpeg伪影)的情况下需要公差)-您可以接受99%的相等性表示相同的图像,50%表示不同的图像
- 颜色更改为geyscaled,反之亦然(因为亮度与颜色无关)
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);
使用此方法一段时间后,我注意到可以做一些改进
获得更高的性能GetPixel
- 使用而不是读取整个图像以提高性能
- 不要将
设置为明暗不同,而是使用所有256像素的不同中值亮度。否则,暗/光图像被假定为相同的,并且它能够检测具有改变的亮度的图像0.5f
- 如果您需要计算,请使用
或bool[]
如果您需要存储大量哈希值并需要节省内存,请使用List
因为布尔值不是存储在一个位中,它需要一段时间李>Bitarray
对于边缘检测和相关计算机视觉算法的开源C#实现,您可以尝试OpenCV的包装。有趣的问题,鉴于此,图像的比较并不难
private List colorList=new List();
私有字符串散列;
私有字符串GetImageHash(位图bmpSource)
{
colorList.Clear();
int i,j;
位图bmpMin=新位图(bmpSource,新大小(16,16));//创建具有16x16像素的新图像
对于(j=0;j
这里的高级内容不错,但很多图像实际上都是同一个文件。我要考虑的一个措施是先做哑巴部分。创建一个目录列表,并按大小顺序对图像文件进行排序。找到具有相同大小文件的所有对,并检查每对是否完全匹配。对于每个匹配项,您可以删除双精度
现在来看有趣的部分
在上述解决方案中,有一件事是没有想到的,那就是利用颜色。您可以使用颜色直方图进行比较。对于红色、绿色和蓝色通道,对每个颜色出现进行计数,并将计数放入树整数[255]数组中。然后将每个RGB数组规格化为浮点[0.0..1.0]值,并作为矢量3(RGB)距离进行比较。这种方法可以找到图像的旋转和调整大小的版本。颜色域中的匹配不能保证。。但是,您可以使用它(再次)对文件进行分组,以进一步优化处理并加快处理速度。使用边缘检测将两个图像缩放到相同大小,然后计算表示差异程度的值(与所有旋转相比)我的帮助-读到这里真的很有趣,但是,只有当图片使用完全相同的算法和完全相同的设置进行修改时,否则您可能会
private List<byte> colorList = new List<byte>();
private string hash;
private string GetImageHash(Bitmap bmpSource)
{
colorList.Clear();
int i,j;
Bitmap bmpMin = new Bitmap(bmpSource, new Size(16, 16)); //create new image with 16x16 pixel
for ( j = 0 ; j < bmpMin.Height; j++)
{
for ( i = 0; i < bmpMin.Width; i++)
{
colorList.Add(bmpMin.GetPixel(i, j).R);
}
}
SHA1Managed sha = new SHA1Managed();
byte[] checksum = sha.ComputeHash(colorList.ToArray());
hash = BitConverter.ToString(checksum).Replace("-", String.Empty);
sha.Dispose();
bmpMin.Dispose();
return hash;
}