imagick / php - 检查图片之间的差异和变化的判断
imagick / php - check the differences between the pictures and the determination of changes
我有两张图片(第一张和第二张 link)。
第三张图片由imagick生成,代码:
$image1 = new \imagick(dirname(dirname(dirname(__DIR__))) . "/1.jpg");
$image2 = new \imagick(dirname(dirname(dirname(__DIR__))) . "/2.jpg");
$result = $image1->compareImages($image2, \Imagick::METRIC_MEANSQUAREERROR);
$result[0]->setImageFormat("jpg");
header("Content-Type: image/jpeg");
echo $result[0];
exit();
我可以用不同的方式表示更改吗?比如红框标出的差异。
这实际上很重要 :-) 有几个问题,首先您需要确定差异 - 您可以通过差分 (-compose difference
) 来做到这一点。然后你需要根据它们的不同程度来对差异进行阈值处理,但是因为你使用的是有损的 JPEG,所以每个像素都有量化结束编码差异。一旦你有了差异,你需要勾勒出它们 - 但如果你天真地勾勒出它们,你会在每个不同的单个像素周围得到一个框,而不是每个形状周围都有一个框,所以你需要做一些模糊和阈值处理(或其他东西else) 将附近的差异合并为单个块。一旦你找到了这些块,你需要在它们周围放一个框架 - 你可以做一个 "Connected Components Analysis" 或其他东西来找到块的边缘 - 我选择了一个"Edge Out Morphology"。然后您需要为边缘着色并将它们合成回原始图像的顶部。该命令在命令行中如下所示:
convert a.jpg \
\( +clone b.jpg -compose difference -composite \
-threshold 1% -separate -evaluate-sequence Add \
-blur 0x5 -threshold 10% \
-morphology edgeout diamond:3 \
-fill red -opaque white -transparent black -write mask.png \) \
-compose srcover -composite result.png
当然,它看起来会有所不同,具体取决于您将轮廓合成到原始两张图片中的哪一张上 - 我选择合成到第一张上,但您可以选择第二张。
我将掩码写入文件 mask.png
这样你就可以看到我在括号内实际构建的内容,我在它周围加了一个边框这样你就可以在下面看到它:
这是您可以尝试的另一种变体 - 很难知道什么最适合您的所有图像:-)
convert a.jpg \
\( +clone b.jpg -compose difference -composite -threshold 1% \
-statistic maximum 25x25 \
-morphology edgeout diamond:5 \
-fill red -opaque white -transparent black -write mask.png \
\) -compose srcover -composite result.png
这个答案与上面的答案类似,只是它在 PHP 中实现。
此外,如果您要这样做,请将差异图像显示为动画。 Gif 或使用 javascript 在图像之间交换。将区域标记为闪烁使用户的生活变得更加轻松。
此外,通过进行两次较小的比较,一次垂直比较,一次水平比较,与一次大比较相比,可以稍微加快处理时间。
$image1 = new Imagick(__DIR__."/compare1.jpg");
$image2 = new Imagick(__DIR__."/compare2.jpg");
$image1->compositeImage($image2, \Imagick::COMPOSITE_DIFFERENCE, 0, 0);
$overlay = clone $image1;
$overlay->negateImage(false);
$overlay->setImageAlphaChannel(\Imagick::ALPHACHANNEL_DEACTIVATE);
$overlay->transformImageColorSpace(\Imagick::COLORSPACE_GRAY);
// Doing one big compare is slow
//$overlay->statisticImage(\Imagick::STATISTIC_MINIMUM, 20, 20);
// Doing a horizontal and vertical compare is faster
$overlay->statisticImage(\Imagick::STATISTIC_MINIMUM, 20, 2);
$overlay->statisticImage(\Imagick::STATISTIC_MINIMUM, 2, 20);
$overlay->statisticImage(\Imagick::STATISTIC_GRADIENT, 4, 4);
$red = new Imagick();
$red->newPseudoImage(
$overlay->getImageWidth(),
$overlay->getImageHeight(),
'xc:red'
);
$red->compositeImage($overlay, \Imagick::COMPOSITE_COPYOPACITY, 0, 0);
$withOutline = clone $image2;
$withOutline->compositeImage($red, \Imagick::COMPOSITE_ATOP, 0, 0);
$outputGif = new Imagick();
$outputGif->addImage($image2);
$outputGif->addImage($withOutline);
$outputGif = $outputGif->deconstructImages();
$outputGif->setImageFormat('gif');
header("Content-Type: image/gif");
echo $outputGif->getImagesBlob();
如您所见,闪烁检测使其更易于查看:
我有两张图片(第一张和第二张 link)。
第三张图片由imagick生成,代码:
$image1 = new \imagick(dirname(dirname(dirname(__DIR__))) . "/1.jpg");
$image2 = new \imagick(dirname(dirname(dirname(__DIR__))) . "/2.jpg");
$result = $image1->compareImages($image2, \Imagick::METRIC_MEANSQUAREERROR);
$result[0]->setImageFormat("jpg");
header("Content-Type: image/jpeg");
echo $result[0];
exit();
我可以用不同的方式表示更改吗?比如红框标出的差异。
这实际上很重要 :-) 有几个问题,首先您需要确定差异 - 您可以通过差分 (-compose difference
) 来做到这一点。然后你需要根据它们的不同程度来对差异进行阈值处理,但是因为你使用的是有损的 JPEG,所以每个像素都有量化结束编码差异。一旦你有了差异,你需要勾勒出它们 - 但如果你天真地勾勒出它们,你会在每个不同的单个像素周围得到一个框,而不是每个形状周围都有一个框,所以你需要做一些模糊和阈值处理(或其他东西else) 将附近的差异合并为单个块。一旦你找到了这些块,你需要在它们周围放一个框架 - 你可以做一个 "Connected Components Analysis" 或其他东西来找到块的边缘 - 我选择了一个"Edge Out Morphology"。然后您需要为边缘着色并将它们合成回原始图像的顶部。该命令在命令行中如下所示:
convert a.jpg \
\( +clone b.jpg -compose difference -composite \
-threshold 1% -separate -evaluate-sequence Add \
-blur 0x5 -threshold 10% \
-morphology edgeout diamond:3 \
-fill red -opaque white -transparent black -write mask.png \) \
-compose srcover -composite result.png
当然,它看起来会有所不同,具体取决于您将轮廓合成到原始两张图片中的哪一张上 - 我选择合成到第一张上,但您可以选择第二张。
我将掩码写入文件 mask.png
这样你就可以看到我在括号内实际构建的内容,我在它周围加了一个边框这样你就可以在下面看到它:
这是您可以尝试的另一种变体 - 很难知道什么最适合您的所有图像:-)
convert a.jpg \
\( +clone b.jpg -compose difference -composite -threshold 1% \
-statistic maximum 25x25 \
-morphology edgeout diamond:5 \
-fill red -opaque white -transparent black -write mask.png \
\) -compose srcover -composite result.png
这个答案与上面的答案类似,只是它在 PHP 中实现。
此外,如果您要这样做,请将差异图像显示为动画。 Gif 或使用 javascript 在图像之间交换。将区域标记为闪烁使用户的生活变得更加轻松。
此外,通过进行两次较小的比较,一次垂直比较,一次水平比较,与一次大比较相比,可以稍微加快处理时间。
$image1 = new Imagick(__DIR__."/compare1.jpg");
$image2 = new Imagick(__DIR__."/compare2.jpg");
$image1->compositeImage($image2, \Imagick::COMPOSITE_DIFFERENCE, 0, 0);
$overlay = clone $image1;
$overlay->negateImage(false);
$overlay->setImageAlphaChannel(\Imagick::ALPHACHANNEL_DEACTIVATE);
$overlay->transformImageColorSpace(\Imagick::COLORSPACE_GRAY);
// Doing one big compare is slow
//$overlay->statisticImage(\Imagick::STATISTIC_MINIMUM, 20, 20);
// Doing a horizontal and vertical compare is faster
$overlay->statisticImage(\Imagick::STATISTIC_MINIMUM, 20, 2);
$overlay->statisticImage(\Imagick::STATISTIC_MINIMUM, 2, 20);
$overlay->statisticImage(\Imagick::STATISTIC_GRADIENT, 4, 4);
$red = new Imagick();
$red->newPseudoImage(
$overlay->getImageWidth(),
$overlay->getImageHeight(),
'xc:red'
);
$red->compositeImage($overlay, \Imagick::COMPOSITE_COPYOPACITY, 0, 0);
$withOutline = clone $image2;
$withOutline->compositeImage($red, \Imagick::COMPOSITE_ATOP, 0, 0);
$outputGif = new Imagick();
$outputGif->addImage($image2);
$outputGif->addImage($withOutline);
$outputGif = $outputGif->deconstructImages();
$outputGif->setImageFormat('gif');
header("Content-Type: image/gif");
echo $outputGif->getImagesBlob();
如您所见,闪烁检测使其更易于查看: