image level normalization

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
User avatar
GreenKoopa
Posts: 457
Joined: 2010-11-04T17:24:08-07:00
Authentication code: 8675308

image level normalization

Post by GreenKoopa »

I would like to stretch the values in my image to the full range. -auto-level seems to be exactly this. However, I have one complication. My image is not square and so has a second image as a mask (no semi-transparent). -auto-level doesn't appear to accept a mask, so I used Copy_Opacity to merge the mask into the primary image as an alpha channel. But -auto-level looks at the color values of my fully transparent pixels, preventing any change at all. Any ideas?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: image level normalization

Post by fmw42 »

try

convert image -channels rgb -auto-level result
User avatar
GreenKoopa
Posts: 457
Joined: 2010-11-04T17:24:08-07:00
Authentication code: 8675308

Re: image level normalization

Post by GreenKoopa »

Thank you for the suggestion, but that didn't help either.

The example:

Code: Select all

convert -size 30x120 gradient:black-white image.png
convert -size 30x40 xc:black xc:white xc:black -append mask.png

convert image.png mask.png -compose Copy_Opacity -composite -auto-level gk_try.png
convert image.png mask.png -compose Copy_Opacity -composite -channel rgb -auto-level fmw42_try.png

convert -bordercolor red image.png mask.png gk_try.png fmw42_try.png -border 2x3 +append post.png
Results in:
Image
(note that all transparent areas are filled in by the red border)

What I would like -auto-level to do is disregard the masked/transparent area.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: image level normalization

Post by fmw42 »

Sorry, I am confused. Both image.png and mask.png are both at the limits of dynamic range. The first is a gradient from black to white, the second is just black and white areas. So -auto-level will not make any change to those. If you wanted to adjust their graylevels, you should do it before you add the alpha channel. If you need to stretch the image such that you saturate at the black and or white levels, then perhaps look at -level and -contrast-stretch.

As I am not quite sure I follow what you are trying to do, perhaps you could try again to explain.

Note, if you look at the verbose info, you will see that your resulting appended image has a completely opaque alpha channel or do

convert 2sacvnq.png -alpha extract 2sacvnq_alpha.png

and look at the image -- it is completely white. But perhaps you created that just to show the individual images you used.

So if that is the case and you want to adjust the two images on the right so that they have more dynamic range, then you have to use -level or -contrast-stretch on the image before you add the alpha channel, since it is really there in its full size which is already at full dynamic range. You are needed to adjust the middle of that full image. But you can only do that by functions that stretch beyond the full dynamic range so that the parts you don't see are saturate to full black and full white.
User avatar
GreenKoopa
Posts: 457
Joined: 2010-11-04T17:24:08-07:00
Authentication code: 8675308

Re: image level normalization

Post by GreenKoopa »

My apologies for being unclear in my first post. I have two input files. One is the image I want -auto-level to work on. The second is a mask, which is black and white (no semi-transparency). The mask is needed because my final image is not square. So I would like -auto-level to stretch the values that matter, the visible ones. Put another way, -auto-level should not look in the areas masked away (or transparent if you prefer) for a minimum or maximum value.

As a trivial example of what I mean, I generate image.png and mask.png. Yes, image.png spans the full range of values. But the top and bottom third are irrelevant. Those values end up being masked/transparent in the end. I would like the middle third, whatever is there, to be stretched to the full range of values.

Did this help clarify any?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: image level normalization

Post by fmw42 »

Yes that is what I thought might be the case, but IM functions do not work that way. They works on everything in the image visible or not. So you have to overstretch the image using -level, +level or easiest -contrast-stretch. In the case of auto-level, since the underlying image is fully stretched it will have no effect on that image (the gradient).

see http://www.imagemagick.org/Usage/color/

compare these three results. I think what you either of the last two.


convert -size 30x120 gradient:black-white \
\( -size 30x40 xc:black xc:white xc:black -append \) \
-compose copy_opacity -composite \
test1.png

convert -size 30x120 gradient:black-white \
\( -size 30x40 xc:black xc:white xc:black -append \) \
-compose copy_opacity -composite -contrast-stretch 20% \
test2.png


convert -size 30x120 gradient:black-white -contrast-stretch 20% \
\( -size 30x40 xc:black xc:white xc:black -append \) \
-compose copy_opacity -composite \
test3.png

However, if you want less contrast, you probably want +level
User avatar
GreenKoopa
Posts: 457
Joined: 2010-11-04T17:24:08-07:00
Authentication code: 8675308

Re: image level normalization

Post by GreenKoopa »

Thank you for the alternatives, but I really do want a full/maximum contrast stretch of the visible area, for any given image and mask. I have come up with one idea. Use -alpha Background to set all the transparent pixels to a middling color that hopefully won't affect -auto-level by still being a minimum or maximum.

But I'm still looking for a more general solution. I discovered -region today. It is the closest conceptually to what I want, but if I could give a mask instead of a geometry. Masks don't have to be square or even contiguous, and can be generated in a huge variety of ways. I'm still pondering but I probably could use some further guidance.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: image level normalization

Post by fmw42 »

IM does not work the way you want currently. But you can always post your suggestions for enhancements to the Developers forum.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: image level normalization

Post by anthony »

At this time -auto-level is a little DUMB.

For example... this command gets an image that has a partial gradient surrounded by transparency.

Code: Select all

convert -size 20x80 gradient:gray30-grey70 -bordercolor none -border 10x10 autolevel_gradient.png
Image

But if you autolevel it. The resulting image was only stretched in the white direction

Code: Select all

convert autolevel_gradient.png -auto-level autolevel_failure.png
Image
ASIDE: the sudden appearance of 'black' instead of transparency in the above IS a bug!
Replacing the PNG output with 'show:' shows a correct image on screen, so it looks like a bug in the PNG coder.
I have reported this in Bugs forum... PNG looses transparency

however that bug does not effect the problem you are having.. the black side of the gradient was NOT stretched.
What is happening is that hidden in the transparency is fully-transparent black! Which as it is black means -auto-level will not stretch the gradients non-black pixels.

This is not a bug, though may be regarded as one, as -auto-level probably should do the right thing for the default case.

ASIDE For the developers. It may be the -channel setting needs a proper 'regard alpha' default setting as a completely separate flag to the default channel settings 'channel' 'sync' flag. The other channel using operators, mathematical composition, and morphology convolve (and the older -convolve) should also use that flag in deciding whether 'alpha' should be ignored or not. Remember 'sync' means handle channels together, with the new flag 'regard alpha' means handle transparency appropriately. and both should be ON by default.


Note this is only a problem with fully-transparent pixels, semi-transparent pixels should always had the 'right' color value.

What is needed is to re-assign all full-transparent pixels some existing visible color (basically any color within the color ranges present in the image), so those pixels do not interfere with the -auto-level's 'dumb' handling.

For example set them all to 50% gray (assuming it is within the images color distribution, which it is.

As such the correct solution is..

Code: Select all

convert autolevel_gradient.png   -background gray50 -alpha background -auto-level   autolevel_correct.png
Image
and that produces the correct result.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: image level normalization

Post by fmw42 »

But then in Anthony's last command, it would seem you would have to re-attach the transparency channel.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: image level normalization

Post by anthony »

I did not re-attach the transparency in the last command. In that command the transparency bug for PNG did not appear! the images shown are the images I got. However after a update that command is also now showing no transparency for me as well.

On the other hand...

Code: Select all

convert -size 20x80 gradient:gray30-grey70 -bordercolor none -border 10x10 -auto-level show:
for the second command shows a correct result while

Code: Select all

convert -size 20x80 gradient:gray30-grey70 -bordercolor none -border 10x10 -background gray50 -alpha background  -auto-level show:
for the thrid command also shows a correct result!

Something is going wrong with PNG. Swicthing them all to using GIF (as I have no semi-transparency to deal with)

Code: Select all

convert -size 20x80 gradient:gray30-grey70 -bordercolor none -border 10x10 autolevel_gradient.gif
convert autolevel_gradient.gif -auto-level autolevel_failure.gif
convert autolevel_gradient.gif   -background gray50 -alpha background -auto-level   autolevel_correct.gif
And all the images work AS EXPECTED!
ImageImageImage

There is a BUG in the PNG results. Transparency should not be touched by -auto-level when the default -channel setting is used. It just currently includes 'transparent colors' in its handling.

When I can get time (no chance right now) I will go in and add a new flag to -channel to have it respect transparency. As I described in the above aside. Suggestions for the -channel flag name welcome.

PS: -normalize and -contrast-stretch and -linear-stretch (all of which I still want to re-design) also all have the same 'hidden transparent color' problem!!!!
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply