python + opencv - 如何正确比较图像(通过直方图)?

标签 python image opencv comparison histogram

我有一堆图像(来自 M.C. Escher 收藏)我想整理,所以我想到的第一步是通过比较它们将它们分组(你知道,有些具有不同的分辨率/形状等) .

我写了一个非常残酷的脚本来: * 读取文件 * 计算它们的直方图 * 比较它们

但是对比的质量真的很低,好像有完全不同的文件匹配

看看我到目前为止写了什么:

准备直方图

files_hist = {}

for i, f in enumerate(files):
    try:
        frame = cv2.imread(f)
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        hist = cv2.calcHist([frame],[0],None,[4096],[0,4096])
        cv2.normalize(hist, hist, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)

        files_hist[f] = hist
    except Exception as e:
        print('ERROR:', f, e)

比较直方图

pairs = list(itertools.combinations(files_hist.keys(), 2))

for i, (f1, f2) in enumerate(pairs):
    correl = cv2.compareHist(files_hist[f1], files_hist[f2], cv2.HISTCMP_CORREL)

    if correl >= 0.999:
        print('MATCH:', correl, f1, f2)

现在,例如,我得到了这两个文件的匹配项:

m._c._escher_244_(1933).jpg m._c._escher_244_(1933).jpg

m._c._escher_208_(1931).jpg m._c._escher_208_(1931).jpg

它们的相关性,使用上面的代码,是 0.9996699595530539(所以它们实际上是相同的 :( )

我做错了什么?我如何改进该代码以避免这种错误匹配?

谢谢!

最佳答案

直方图不是比较图像的好方法,例如,在黑白图像中,如果它们具有相同数量的黑色像素,则直方图将相同,无论图像中的像素分布如何(这就是为什么您提到的图像被归类为几乎相等)。

有更好的方法来量化图像之间的差异,this post提到了一个不错的选择:

  • 将两个图像加载为数组 (scipy.misc.imread) 并计算逐个元素(逐个像素)的差异。计算差异的范数。

编辑:

回答一些问题:

I take the zero norm per-pixel is going to be 0.0-1.0 value, with values close to 0.0 meaning "images are the same", correct?

接近 0.0 的值表示像素相同。要将图像作为一个整体进行比较,您需要对所有像素求和。如果总和值接近 0.0,则表示图像几乎相同。

what if the 2 image sizes are different?

这是一个很好的。要计算范数差,图像必须具有相同的大小。我看到了实现这一目标的两种方法:

  • 第一个是将其中一张图片调整为另一张图片的形状,问题是这会导致图片失真。

  • 第二个是用零填充较小的图像,直到大小匹配。

obs:如果对像素范数求和,您将得到一个介于零和图像中像素数之间的值。如果您比较多个图像,这可能会造成混淆。例如,假设您正在比较图像 A 和 B,并且两者的形状均为 50x50(因此,图像具有 2500 像素);接近 2500 的值意味着图像完全不同。现在假设您正在比较图像 C 和 D,并且两者的形状均为 1000x1000,在这种情况下,像 2500 这样的值意味着图像相似。为了解决这个问题,您可以将按像素求和除以图像中的像素数,这将得到介于 0.0 和 1.0 之间的值,0.0 表示图像相同,1.0 表示它们完全不同。

yeah here's the error i received when comparing 2 images with different size diff = image1 - image2 ValueError: operands could not be broadcast together with shapes (850,534) (663,650)

发生这种情况是因为图像具有不同的形状。调整大小或填充可以避免此错误(如上所述)。

关于python + opencv - 如何正确比较图像(通过直方图)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55551404/

相关文章:

python - 展平混合类型的列表

python - 如何使用 Metropolis Hastings 从 Gamma(26,6) 分布中采样

opencv4android 示例编译但不运行

即使 WITH_CUDA=ON 在 CMake 中,OpenCV 也不会使用 CUDA 构建

python - 如何在pygame中点击并拖动一个对象?

python - 有没有更好的方法来构建它以便打印类/父类的所有属性

每次旋转后 PHP 图像旋转都会失去质量

ios - 将 RGB 图像转换为灰度并将灰度转换为 RGB 图像?

css - 为什么使用手机时,flex div 中 25% 宽度的 img 之间会出现一些间隙?

c++ - OpenCV:如何使用阈值正确分割图像/使用二进制图像分割原始图像?