比较图像文件

-1 投票
3 回答
4143 浏览
提问于 2025-04-17 10:55

我想写一个程序,用来比较两张图片。这个程序需要输入两个文件夹,每个文件夹里都有很多图片,而且每个文件夹里的图片名字是一样的。比如说,文件夹1里有三张图片:[a.png, b.png, c.png],而文件夹2里也有三张图片:[a.png, b.png, c.png]。我想把文件夹1里的a.png和文件夹2里的a.png进行比较。但是我不知道从哪里开始。

3 个回答

1

这里有一个C#的解决方案,它通过二进制文件比较来对比文件。不过,即使两张图片看起来一样,它们可能包含不同的元信息。因此,比较之前,最好先把图片作为图像打开,而不仅仅是当作文件来比较。

public void CompareImages()
{
    var dir1 = new DirectoryInfo(@"C:\path1");
    FileInfo[] files1 = dir1.GetFiles("*.png");

    var dir2 = new DirectoryInfo(@"C:\path2");
    FileInfo[] files2 = dir2.GetFiles("*.png");
    Dictionary<string, FileInfo> files2Dict = files2.ToDictionary(f => f.Name);

    foreach (FileInfo f1 in files1) {
        FileInfo f2;
        bool equal = true;
        if (files2Dict.TryGetValue(f1.Name, out f2) && f1.Length == f2.Length) {
            byte[] image1 = GetFileBytes(f1);
            byte[] image2 = GetFileBytes(f2);
            for (int i = 0; i < image1.Length; i++) {
                if (image1[i] != image2[i]) {
                    equal = false;
                    break;
                }
            }
        } else {
            equal = false;
        }
        Console.WriteLine(f1.Name + ": " + (equal ? "Images are equal" : "Images are NOT equal"));
    }
}

private static byte[] GetFileBytes(FileInfo f)
{
    using (FileStream stream = f.OpenRead()) {
        byte[] buffer = new byte[f.Length];
        stream.Read(buffer, 0, (int)f.Length);
        return buffer;
    }
}
1

你在考虑用 C#、Python 还是 C 吗?

可以看看这些链接:

如何用 C# .NET 比较图像对象?

用 Python/Linux 的方法比较两张图片

祝你好运!

3

你提到的是 images 而不是 file,所以我猜测你想比较的不是原始数据,而是图像的像素,并且你可能还想设定一个阈值来判断图像之间的差异。

最简单的方法是使用 PIL 来比较两张图片。PIL 有一个 histogram 函数,你可以用它来获取两张图片的直方图,然后计算一个 RMS(均方根)值,比如:

import ImageChops
import math, operator

def rmsdiff(im1, im2):
    "Calculate the root-mean-square difference between two images"

    h = ImageChops.difference(im1, im2).histogram()

    # calculate rms
    return math.sqrt(reduce(operator.add,
        map(lambda h, i: h*(i**2), h, range(256))
    ) / (float(im1.size[0]) * im1.size[1]))

这段内容是从 http://effbot.org/zone/pil-comparing-images.htm 复制过来的。

一旦你有了一个返回 rmsdiff 的函数,你就可以在另一个函数中使用它,这个函数会遍历所有的文件,比如:

def diff_folder(folder1, folder2):
    for path1 in glob.glob(folder1+"/*.png"):
        filename = os.path.basename(path1)
        path2 = os.path.join(folder2, filename)
        if not os.path.exists(path2):
            continue
        im1 = Image.open(path1)
        im2 = Image.open(path2)
        diff = rmsdiff(im1, im2)
        if diff > threshold:
           print "different"

撰写回答