Compare two images and highlight the differences along the second image

Below is the current working code in python using PIL to highlight the difference between two images. But the rest of the images turn black.

Currently, I want to show the background along with the selected image.

Is there anyway, I can keep the background highlight and just highlight the differences.

from PIL import Image, ImageChops point_table = ([0] + ([255] * 255)) def black_or_b(a, b): diff = ImageChops.difference(a, b) diff = diff.convert('L') # diff = diff.point(point_table) h,w=diff.size new = diff.convert('RGB') new.paste(b, mask=diff) return new a = Image.open('i1.png') b = Image.open('i2.png') c = black_or_b(a, b) c.save('diff.png') 

! https://drive.google.com/file/d/0BylgVQ7RN4ZhTUtUU1hmc1FUVlE/view?usp=sharing

+5
source share
3 answers

PIL has some convenient ways to manipulate images, but there are also many disadvantages when a person wants to start serious image processing -

Most Python records recommend that you switch to using NumPy over your pixel data, which will give you complete control - Other image libraries such as leptonica, gegl and vips all have Python bindings and some nice features for composing / segmenting the image.

In this case, you need to imagine how you could get the desired result in the image processing program: You will have a black (or other color) shade of the original image, and above this, insert the second image, but using a threshold value (that is, the pixel is equal to or equals different - all intermediate values โ€‹โ€‹should be rounded to โ€œdifferentโ€ differences in the quality of the mask to the second image.

I modified your function to create such a composition -

 from PIL import Image, ImageChops, ImageDraw point_table = ([0] + ([255] * 255)) def new_gray(size, color): img = Image.new('L',size) dr = ImageDraw.Draw(img) dr.rectangle((0,0) + size, color) return img def black_or_b(a, b, opacity=0.85): diff = ImageChops.difference(a, b) diff = diff.convert('L') # Hack: there is no threshold in PILL, # so we add the difference with itself to do # a poor man thresholding of the mask: #(the values for equal pixels- 0 - don't add up) thresholded_diff = diff for repeat in range(3): thresholded_diff = ImageChops.add(thresholded_diff, thresholded_diff) h,w = size = diff.size mask = new_gray(size, int(255 * (opacity))) shade = new_gray(size, 0) new = a.copy() new.paste(shade, mask=mask) # To have the original image show partially # on the final result, simply put "diff" instead of thresholded_diff bellow new.paste(b, mask=thresholded_diff) return new a = Image.open('a.png') b = Image.open('b.png') c = black_or_b(a, b) c.save('c.png') 
+5
source

Here is the solution using libvips:

 import sys from gi.repository import Vips a = Vips.Image.new_from_file(sys.argv[1], access = Vips.Access.SEQUENTIAL) b = Vips.Image.new_from_file(sys.argv[2], access = Vips.Access.SEQUENTIAL) # a != b makes an N-band image with 0/255 for false/true ... we have to OR the # bands together to get a 1-band mask image which is true for pixels which # differ in any band mask = (a != b).bandbool("or") # now pick pixels from a or b with the mask ... dim false pixels down diff = mask.ifthenelse(a, b * 0.2) diff.write_to_file(sys.argv[3]) 

With PNG images, most CPU hours are spent reading and writing PNGs, so vips is only slightly faster than the PIL solution.

libvips uses a lot less memory, especially for large images. libvips is a streaming library: it can load, process and save the result at the same time, it is not necessary that the whole image is loaded into memory before it can start working.

For 10,000 x 10,000 RGB tif libvips is about twice as fast and requires about 1/10 of the memory.

+1
source

If you're not attached to the idea of โ€‹โ€‹using Python, there are some really simple solutions using ImageMagick:

"Diff" image using ImageMagick

0
source

All Articles