MagickNET - Compare two pictures and show only difference, rest transparent

492 Views Asked by At

Goal: Compare two PNG images and creating a new image containing only the changes (not highlighted in red or anything), while the rest of the png is transparent.

            MagickImage newImg = new MagickImage(image2Path);

            MagickImage oldImage = new MagickImage(diffImagePath);

            oldImage.Compose = CompositeOperator.Difference;

            var diffimage = new MagickImage();

            using (var imgDiff = new MagickImage())
            {
                double diffd = newImg.Compare(oldImage, ErrorMetric.Absolute, diffimage);
            }

What I'm ending up with when comparing two identical pictures is the same, but with a little opacity.

Any help is appreciated.

EDIT: Basically what I would like to end up is this. But instead of the result having a white background, I would like it to be transparent. enter image description here

2

There are 2 best solutions below

1
On

In command line ImageMagick, this would be how to do that. Sorry, I am not a Magick.Net user. But the translation should be obvious.

Car1:

enter image description here

Car2:

enter image description here

compare -highlight-color red -lowlight-color none -compose src car1.png car2.png diff.png

enter image description here

1
On

I find Magick.Net and ImageMagick in general annoying to use via APIs in general, because all documentation describes the command line, so you sort of have to guess how to translate into API calls.

This is one approach I managed to hobble together. Maybe there's a more elegant way.

Input:

Car with writing Car without writing

var newImg = new MagickImage(pathToCarWithWriting);
var oldImg = new MagickImage(pathToBlankCar);

// Calcluate a greyscale mask for any changed pixels.
// The mask should not have an alpha channel so it can work with Copy_Opacity
// The 'treshold' value of 60% is stolen from 
// https://stackoverflow.com/questions/38060940/how-to-create-black-and-white-images-in-magick-net
var diffMask = newImg.Clone();
diffMask.Composite(oldImg, CompositeOperator.Difference, Channels.RGB);
// Convert to greyscale
diffMask.Threshold(new Percentage(60));


var changed = newImg.Clone();
// Overlay a greyscale mask to the new image, using CopyAlpha
// (which does not copy the alpha channel when the overlay has no alpha channel, but instead treats it as a mask)
// Now only the areas that are different in newImg and oldImg will be visible in Changed.
changed.Composite(diffMask, CompositeOperator.CopyAlpha);

Result (which is transparent except for the yellow):

enter image description here