Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Making pixels with different colors transparent when comparing 2 images #3754

Open
vicegold opened this issue Aug 6, 2023 · 5 comments
Open
Labels

Comments

@vicegold
Copy link

vicegold commented Aug 6, 2023

Hi, I got 2 images with are quite similar, but have a different background color. I want to use these different colors to make all those pixels transparent.

So when I have these 2 images:
test-black
test-white

the result would be this:
test-transparent

I got this working with Imagick, but don't even know where to start with Sharp/libvips:

convert test-black.png test-white.png -alpha off \
          \( -clone 0,1 -compose difference -composite -negate \) \
          \( -clone 0,2 +swap -compose divide -composite \) \
          -delete 0,1 +swap -compose Copy_Opacity -composite \
          test-transparent.png

Anybody got some ideas how I could do this in Sharp?

@vicegold vicegold changed the title Remove pixels with different colors when comparing 2 images Making pixels with different colors transparent when comparing 2 images Aug 6, 2023
@antonmarsden
Copy link
Contributor

antonmarsden commented Aug 9, 2023

@vicegold Could potentially use the unflatten function for this. It will convert pure white to transparent. You could then invert the colours and unflatten again to deal with the black background.

Might be tricky to deal with the white in the centre star though.

@lovell
Copy link
Owner

lovell commented Sep 18, 2023

The difference composite blend mode can be used to work out the absolute difference between the two images and therefore provide a mask.

https://sharp.pixelplumbing.com/api-composite

await sharp('input1.png')
  .composite([{ input: 'input2.png', blend: 'difference' }])
  .toFile('mask.png');

As @antonmarsden suggests, you can then use unflatten to convert white pixels to transparent, and then use the in composite blend mode to apply the transparent mask to the initial input.

https://sharp.pixelplumbing.com/api-operation#unflatten

await sharp('mask.png')
  .unflatten()
  .composite([{ input: 'input1.png', blend: 'in' }])
  .toFile('out.png');

There is some aliasing around the edge, but I think this is present in the original images. Are they premultipled? You might need to experiment with the premultiplied option of composite if so.

@lovell
Copy link
Owner

lovell commented Oct 5, 2023

@vicegold Were you able to make any progress with this?

@vicegold
Copy link
Author

vicegold commented Oct 9, 2023

@antonmarsden @lovell Sorry for the very late reply and thanks for your help!

I've come closer to the desired result, but unfortunately can't overcome the aliasing issue. The images are not premultiplied, but I've also made sure to flatten my test images before running them through sharp. The mask always turns out fine, but applying the mask results in inaccurate edges. Using the premultiplied options doesn't seem to have any effect with these images.

Here's my results.

Sources:
white
black

Here's the resulting mask:
mask

And here's the final image with the mask applied:
out

Will try to debug more to find what's causing the aliasing.

@lovell
Copy link
Owner

lovell commented May 16, 2024

@vicegold Were you able to make any progress with this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants