比较图像以呈现差异(忽略抗锯齿)

时间:2017-08-29 18:35:05

标签: image compare imagemagick

我有一个PDF文件,我使用Adobe PDF引擎以及另一个PDF翻录渲染。我想尝试识别它们以不同方式呈现的位置。问题是它们都具有略微不同的抗锯齿,颜色和非常小的位置差异。我更关注更大的差异。我想比较附件match1.pngmatch2.png。这两个应该匹配。文件diff1.pngdiff2.png不匹配。他们应该失败,因为一个人丢失了一封信。我曾经使用过ImageMagick的比较,但是没有足够好的结果来忽略轻微的渲染差异而只关注主要的差异。我认为下面的算法可以工作,但我不确定如何读取PNG文件并逐个像素地比较它们。

sample image files

  1. 将ImageA中的每个像素与ImageB中的相同像素进行比较。还要与ImageB中的每个相邻像素进行比较
  2. 从ImageB中的所有测试像素中找到最接近的匹配像素。
  3. 将此最接近的匹配像素的色差存储为ImageA中该像素的差异索引。
  4. 对ImageA中的每个像素重复此计算。
  5. 归一化差值,使最小差值为零。未标准化的值可能是(3,8,5,18),标准化可能是(0,5,2,15)或其他类型的标准化函数。
  6. 然后计算超过阈值的像素数,例如5或其他。那么这个“坏”的数字就算了。像素可用于计算其中一个图像中存在渲染错误的概率。
  7. 这只是一个示例算法。我不确定如何逐像素处理PNG文件。我可以使用命令行工具(如imagemagick等)对PHP解决方案或解决方案开放。

2 个答案:

答案 0 :(得分:0)

如果您闪烁两个匹配图像(交替显示一个然后另一个和来回显示),您将看到两个橙色颜色不同。由于边缘处的抗锯齿,这不仅仅是差异。

因此,使用Imagemagick 6,compare将显示相当多的变化(如红色)。如果使用Imagemagick 7,请使用magick compare。请参阅http://www.imagemagick.org/Usage/compare/#compare

function getTopRatings($category) {
    $pdo = Database::connect();
    $sql = "SELECT item, rating, items.id, items.name FROM ratings INNER JOIN items ON ratings.item=items.id WHERE category = '" . $category . "'";
    $pdo->query($sql);
    foreach ($pdo->query($sql) as $row) {
        $ratings[] = array(
            "itemid" => $row['id'],
            "name" => $row['name'],
            "rating" => ?
        );
    }
    Database::disconnect();
}

这里差异是3.5%,但差异图像显示很多红色,因为每个像素都有不同的值。

enter image description here

另一种看待差异的方法是使用-compose差异。结果越白,差异越大。

compare -metric rmse match1.png match2.png match_diff.png
2304.18 (0.0351595)

enter image description here

这并没有太大的不同,所以所有的值都只是略有不同。但是通过拉伸动态范围,您可以看到它最不同的地方。

检查相邻像素的一种方法是重复比较在每个方向上移动一个图像1像素(使用-roll + X + Y)并且可能使用-shave XxY修剪每个图像周围的1个像素。您可以循环执行此操作并保存每个结果。然后使用-evaluate-sequence min查找同一像素位置的每个图像的最小(最近像素值)。这相当于搜索比较的3x3邻域。问题是你不知道哪个图像给出了最大的结果。

enter image description here

P.S。你也可以使用compare -metric AE -fuzz 5%。模糊值将允许比较忽略该百分比内的值。这似乎不适用于Imagemagick 6.9.9.10,但在Imagemagick 7.0.6.10中有效。

convert match1.png match2.png -compose difference -composite match_diff2.png

219487

这表示任意数量的219487像素不匹配。这是他们不同的地方。

enter image description here

答案 1 :(得分:0)

我会稍微模糊图像以去除任何细节,然后寻找最大差异。一个简单的差异指标是dE76Spatial CIELAB做了一些非常相似的事情(如果有点发烧友)。

以下是使用php-vips的实现:

#!/usr/bin/env php
<?php

require __DIR__ . '/vendor/autoload.php';
use Jcupitt\Vips;

$a = Vips\Image::newFromFile($argv[1]);
$b = Vips\Image::newFromFile($argv[2]);

$a = $a->gaussblur(2);
$b = $b->gaussblur(2);
$diff = $a->dE76($b);

# output a 500 pixel across difference map
$scale = 500.0 / $diff->width;
$diff->multiply(5)->resize($scale)->writeToFile("map.png");

echo("maximum image difference is " . $diff->max() . " dE76\n");

对于你的图片,我看到了:

$ ./measure_diff.php match1.png match2.png 
maximum image difference is 13.739426612854 dE76
$ ./measure_diff.php diff1.png diff2.png 
maximum image difference is 55.040554046631 dE76

第一对中的13只是色彩渲染的差异,第二对中的55是额外的逗号。它在地图上非常明显:

enter image description here