Reputation: 436
I have two images (first and second link).
Third image was generated by imagick, by code:
$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();
Can I indicate changes in a different way? For example, differences marked red frame.
Upvotes: 2
Views: 1437
Reputation: 25701
This answer is similar to the one above, except it's implemented in PHP.
Also, if you're going to do something like this, please present the difference image as an animation. Either a Gif or using javascript to swap between images. Having the regions marked be flashing makes life so much easier for users.
Also, the processing time can be sped up a little by doing two smaller compares, one vertical and one horizontal compared to one big compare.
$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();
As you can see the flashing detection makes it much easier to see:
Upvotes: 3
Reputation: 207425
That is actually non-trivial :-) There are a couple of issues, firstly you need to identify the differences - you can do that by differencing (-compose difference
). Then you need to threshold the differences according to how much they differ, but because you are using JPEG which is lossy, there are quantisation end encoding differences at every pixel. Once you have the differences, you need to outline them - but if you outline them naively, you will get a box around every singel pixel that differs instead of one box around each shape, so you need to do some blurring and thresholding (or something else) to merge nearby differences into single lumps. Once you have found the lumps, you need to put a frame around them - you could either do a "Connected Components Analysis" or something else to find the edges of the lumps - I chose an "Edge Out Morphology". Then you need to colour the edges and composite them back on top of the original image. The command looks like this on the command line:
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
It will of course look different depending on which of the original two pictures you composite the outlines onto - I chose to composite onto the first one, but you could choose the second.
I wrote out the mask into the file mask.png
so you can see what I am actually building up inside the parentheses, and I put a border around it so you can see it below:
Here is another variation for you to experiment with - it is hard to know what will work best with all your images:-)
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
Upvotes: 3