我正在开发一个应用程序,我可以在列表中加载多张图片,并将该列表中的每张图片与其他图片进行比较,以便找到重复的图片。
首先,我成功获得了图片并将其加载到IList<Bitmap>
:
public IList<Bitmap> getPictures()
{
IList<Bitmap> pictures = new List<Bitmap>();
string filepath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
DirectoryInfo d = new DirectoryInfo(filepath+ "\\Phone Pictures\\");
foreach (var picture in d.GetFiles("*.png"))
{
pictures.Add(ConvertToBitmap(picture.FullName));
}
return pictures;
}
比我使用预先制作的图像比较算法:
public static CompareResult Compare(Bitmap bmp1, Bitmap bmp2)
{
CompareResult cr = CompareResult.ciCompareOk;
//Test to see if we have the same size of image
if (bmp1.Size != bmp2.Size)
{
cr = CompareResult.ciSizeMismatch;
}
else
{
//Convert each image to a byte array
System.Drawing.ImageConverter ic =
new System.Drawing.ImageConverter();
byte[] btImage1 = new byte[1];
btImage1 = (byte[])ic.ConvertTo(bmp1, btImage1.GetType());
byte[] btImage2 = new byte[1];
btImage2 = (byte[])ic.ConvertTo(bmp2, btImage2.GetType());
//Compute a hash for each image
SHA256Managed shaM = new SHA256Managed();
byte[] hash1 = shaM.ComputeHash(btImage1);
byte[] hash2 = shaM.ComputeHash(btImage2);
//Compare the hash values
for (int i = 0; i < hash1.Length && i < hash2.Length
&& cr == CompareResult.ciCompareOk; i++)
{
if (hash1[i] != hash2[i])
cr = CompareResult.ciPixelMismatch;
}
}
return cr;
}
现在我尝试调用算法并将其应用到我加载的列表中:
public void ComparePictureList()
{
IList<Bitmap> picturesList = getPictures();
foreach (var picture1 in picturesList)
{
foreach( var picture2 in picturesList)
{
Compare(picture1, picture2);
}
}
}
但有没有更好的方法将我的算法应用到我的列表中,我的意思是代替而不是声明2个循环picture1
和picture2
.NET
框架中是否有任何功能可以好吗?
P.S:对于任何想知道ConvertToBitmap
是什么的人来说:
public Bitmap ConvertToBitmap(string fileName)
{
Bitmap bitmap;
using (Stream bmpStream = System.IO.File.Open(fileName, System.IO.FileMode.Open))
{
Image image = Image.FromStream(bmpStream);
bitmap = new Bitmap(image);
}
return bitmap;
}
答案 0 :(得分:3)
我会避免为同一个图像多次计算哈希值,并且只在图像中循环一次:
public static void Main(string[] args)
{
var files = new Dictionary<string, string>();
foreach (var file in Directory.GetFiles("c:\\", "*.png"))
{
files.Add(file, CalculateHash(file));
}
var duplicates = files.GroupBy(item => item.Value).Where(group => group.Count() > 1);
}
private static string CalculateHash(string file)
{
using (var stream = File.OpenRead(file))
{
var sha = new SHA256Managed();
var checksum = sha.ComputeHash(stream);
return BitConverter.ToString(checksum).Replace("-", String.Empty);
}
}
答案 1 :(得分:2)
您无法确定具有相同哈希的两个图像是否相等。
如果您的散列函数使用图像的所有字节,您可以更快地比较图像的字节而不是计算散列并比较它们。
您多次计算每个图像的哈希值。你不需要这样做。
我建议您执行以下操作:
计算每个图像的哈希并存储它。
使用地图或两个循环来查找哈希冲突。
需要逐个比较具有相同散列的图像,以确保它们相等。
答案 2 :(得分:1)
您已经在计算每张图片的哈希值,因此您可以将其转换为例如String
然后只使用Dictionary<String, Bitmap>
,其中Key
将是哈希值。您可以使用ContainsKey
快速确定图像哈希是否已在列表中。
由于您是通过流打开图像文件,因此可以更简单地计算Stream
中的哈希值,如Calculate the Hash of the Contents of a File in C#?所述。您可能需要回放流才能读取图像。