getting alpha by subtracting two images with different backg

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
zsero
Posts: 9
Joined: 2011-07-13T13:55:51-07:00
Authentication code: 8675308

getting alpha by subtracting two images with different backg

Post by zsero »

I am using a program what can render color images but only without alpha information. I would like to get alpha information from those images by using two and subtracting them. I can set the background to different colors.

My idea is that if I render an image with black background and an other one with white, then I can subtract those images from each other and get an alpha channel. But it is just a theory, I don't know how to do it in practise and that if there are any standard methods / algorithms for extracting alpha information out of two images by subtracting them from each other.

I would like to use a command line program (or a very easy to use library in C++) to do this processing. I have used convert.exe from ImageMagick before, but I have never used the other utilities in ImageMagick.

Is there anyone who can recommend me a way how to do it in practise? What I am looking for is some kind of a command line solution or a C++ library with easy to understand example files what can do this.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: getting alpha by subtracting two images with different b

Post by fmw42 »

Best I can suggest is:

http://www.imagemagick.org/Usage/masking/#semi-trans
and
http://www.imagemagick.org/Usage/maskin ... background

I have never experimented with this, but Anthony has created these two examples. Perhaps that will help or he can comment further.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: getting alpha by subtracting two images with different b

Post by anthony »

If the two background colors are very different in the three color channels, you can do a perfect recovery of the alpha using the method described by the second link above.
http://www.imagemagick.org/Usage/maskin ... background

The subtraction is the correct first step, but only to determine the actial alpha transparency. The tricky part was to them combine that alpha with one of the original images, and its known background to correctly determine the original (un-blended) color of semi-transparent pixels.

Major thanks goes to HugoRune of this forum discussion
http://www.imagemagick.org/Usage/forum_link.cgi?t=18235
for working out the maths needed to restore the colors.

For a image on a black background the color recovery actually simplifies to a division by the alpha channel. See last example in the above IM Examples link.


If you a small example (resize them if needed), we could have a loot to see how practical the recovery is.

WARNING: reflections and refractions in object being recovered may not turn out very well.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
zsero
Posts: 9
Joined: 2011-07-13T13:55:51-07:00
Authentication code: 8675308

Re: getting alpha by subtracting two images with different b

Post by zsero »

Thanks for the great replies!

My case is quite lucky, as I have computer generated images, which means that the background is 100% solid color, and there are no real world relfections or anything whatsoever. I think its best if I share an example image pair, as it explains things better than I could with words:

Image
Image

What I would like to have is the black image with an 8-bit alpha layer, in a PNG file. Could you tell me what would be the best command to do this? Also, someone recommended me this command. Do you think it works? If you would like to look at the original PNG's, then I have uploaded them here:
http://ifile.it/klq6g1m
http://ifile.it/7b1xsgn

Code: Select all

 convert <image1> <image2> -alpha off \
          \( -clone 0,1 -compose difference -composite -negate \) \
          \( -clone 0,2 +swap -compose divide -composite \) \
          -delete 0,1 +swap -compose Copy_Opacity -composite \
          <output>
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: getting alpha by subtracting two images with different b

Post by fmw42 »

just follow Anthony's example at http://www.imagemagick.org/Usage/maskin ... background

Here it is in two steps and again in one combined step using your image (though I renamed wHaW3l.jpg to 9wHaW3l.jpg to keep them together in my directory)

try either these two commands :

convert 9jIJwl.jpg 9wHaW3l.jpg \
-compose difference -composite -separate \
-evaluate-sequence max -auto-level -negate \
9apple_alpha.png

convert 9jIJwl.jpg 9apple_alpha.png -alpha Off \
-monitor -fx "v==0 ? 0 : u/v - u.p{0,0}/v + u.p{0,0}" +monitor \
9apple_alpha.png -compose Copy_Opacity -composite \
9apple_recovered.png


or this one command

convert 9jIJwl.jpg 9wHaW3l.jpg \
\( -clone 0 -clone 1 -compose difference -composite -separate \
-evaluate-sequence max -auto-level -negate \) \
\( -clone 0 -clone 2 -alpha Off \
-monitor -fx "v==0 ? 0 : u/v - u.p{0,0}/v + u.p{0,0}" +monitor \
-clone 2 -compose Copy_Opacity -composite \) \
-delete 0-2 9apple_recovered2.png

They work fine for me on IM 6.7.1.0 Q16 Mac OSX Tiger. If on windows, see differences in syntax at http://www.imagemagick.org/Usage/windows/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: getting alpha by subtracting two images with different b

Post by anthony »

With pure black and white the last example will recover the transparency..

Code: Select all

  convert f9jIJwl.jpg  wHaW3l.jpg -alpha off \
          \( -clone 0,1 -compose difference -composite -negate \) \
          \( -clone 0,2 +swap -compose divide -composite \) \
          -delete 0,1 +swap -compose Copy_Opacity -composite \
          result.png
Remember you can not save transparency to JPEG.

I would however recommend NOT using JPEG for input either, or you may get some JPEG compression noise in the result.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
zsero
Posts: 9
Joined: 2011-07-13T13:55:51-07:00
Authentication code: 8675308

Re: getting alpha by subtracting two images with different b

Post by zsero »

Thank you all, this script works wonderfully!

My only problem so far is that when there is no object on the image (it happens in an animation), then the result PNG image (100% transparent blank image) does not open up in some application. When I open it in Photoshop, instead of being 100% transparent, it is 100% solid black.

Is there any switch or something which could set ImageMagick in a mode to save this 100% transparent PNG files differently?

I have no way of knowing which image is transparent and which is not, the source is an image sequence from an animation what I cannot inspect for every frame.

Here is the result PNG file. Its 456 bytes in length.
http://www.mediafire.com/imageview.php? ... 97&thumb=4
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: getting alpha by subtracting two images with different b

Post by fmw42 »

There is nothing wrong with your image. It is transparent on my viewers. identify -verbose yourimage looks fine to me.

Some viewers don't handle solid transparency well. The only thing that I can suggest might be to add -strip to your command to remove any profiles and other meta data and see if your other viewers will handle it better. Your verbose info shows a lot of PNG controls. Perhaps the PNG format you have is not compatible with all viewers. You would need to hear back from the PNG developer, glennrp, for more details as to whether this might be your issue.

You could test whether the image was pure transparent and throw it out. You would need to write a short script. The alpha channel will have 0 for min and max. Those are easy to get with string formats or fx calculations.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: getting alpha by subtracting two images with different b

Post by anthony »

Be careful. A blank image can be vital in an animation. I have seen animations with blank frames that are used as a means of setting correct disposal handling in preparation for the next frames overlay.

This especially happens when you combine Frame Doubling Optimization
http://www.imagemagick.org/Usage/anim_opt/#doubling
with transparency compression optimization
http://www.imagemagick.org/Usage/anim_opt/#opt_trans

Basically the additional frame does not change the image, just define the are to make transparent, then the transparency optimization makes that frame completely blank. It works and is correct.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
zsero
Posts: 9
Joined: 2011-07-13T13:55:51-07:00
Authentication code: 8675308

Re: getting alpha by subtracting two images with different b

Post by zsero »

I've been using this script for a while now, its fantastic! Thanks for it!

I only have a little question, what is that how to resample the given images to a smaller resolution, _after_ the alpha processing has taken effect?

Is this the correct line?

Code: Select all

convert.exe x_black0001.png x_white0001.png -alpha off ( -clone 0,1 -compose difference -composite -negate ) ( -clone 0,2 +swap -compose divide -composite ) -delete 0,1 +swap -compose Copy_Opacity -filter lanczos -composite -resize "1920x1080>" x_alpha0001.png
In ImageMagick, what "priority" does resize have over other commands? Or is it the order of the arguments?
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: getting alpha by subtracting two images with different b

Post by anthony »

The resize should be able to be performed either before recovering alpha, or after. IT should not effect the final result of the background recovery. If you are using -fx for the recovery process, reducing the size first may speed things up, as -fx is that slow. BUT for a non -fx method (recovering background using the 'black' source image, and thus using a composite 'divide') size should not be as important. Experiment and find out is my best suggestion!

Option order was the major difference between IMv5 and IMv6. IMv6 performs all operations in the order they are given on the command line. IMv5 typically applied options in a fixed order, whcih was not nessarially command line order. It made image processing very awkward and tricky as you could never be certain things were applied in the right order. As a consequence you generally could only do a few simple image operations per command! IMv6 allows hundreds of operations in a single command.

The ONLY exception to this was when IM had yet to read/create an image. In that case it will apply all settings up to the first image read, then re-run thru all options after the first image has been read in again. It was a backward compatibly thing for simple IMv5 scripts.

So in answer, order is command line order. and you should be reading in at least one image before trying to apply an operation on that image.

WARNING: IMv7 will likely make it an error to attempt to perform an operation when no image has been read into memory! That is because it will loose that 'backtrack' capability (at least for the 'primary' command which was "convert" in IMv6) as part of allowing it to handle applying operations that are read from a script or pipeline.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply