possible bug -sigmoidal-contrast IM 6.7.5.7 Q16

Post any defects you find in the released or beta versions of the ImageMagick software here. Include the ImageMagick version, OS, and any command-line required to reproduce the problem. Got a patch for a bug? Post it here.
Post Reply
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

possible bug -sigmoidal-contrast IM 6.7.5.7 Q16

Post by fmw42 »

IM 6.7.5.7 Q16 Mac OSX Snow Leopard

I am not sure if this is a bug or just a limitation and that the documentation needs changing?

The documentation on the options page says,

-sigmoidal-contrast contrastxmid-point

Increase the contrast of the image using a sigmoidal transfer function without saturating highlights or shadows. Contrast indicates how much to increase the contrast (0 is none; 3 is typical; 20 is a lot);

So I assume a value of -sigmoidal-contrast 0,50% would mean no change to the image. But I get a black image.

convert rose: -sigmoidal-contrast 0,50% rose_sigm_0x50.png
compare -metric rmse rose: rose_sigm_0x50.png null:
31915.9 (0.487005)


However, any tiny value for example 0.1 or even 0.00001, however, is virtually no change. (A value of 1 is too much).

convert rose: -sigmoidal-contrast 0.1,50% rose_sigm_0p1x50.png

compare -metric rmse rose: rose_sigm_0p1x50.png null:
0 (0)


convert rose: -sigmoidal-contrast 0.00001,50% rose_sigm0p00001x50.png
compare -metric rmse rose: rose_sigm0p00001x50.png null:
0 (0)

convert rose: -sigmoidal-contrast 1,50% rose_sigm1x50.png
compare -metric rmse rose: rose_sigm1x50.png null:
228.286 (0.00348342)



Should the code 1) automatically trap on zero and make it no-op, 2) or add some small number (quantumscale is too small and does not work) to the user provided argument or 3) should the docs be changed to indicate the smallest (or range of) non-zero values to use that results in no change?
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: possible bug -sigmoidal-contrast IM 6.7.5.7 Q16

Post by magick »

1 means no change. See http://osdir.com/ml/video.image-magick. ... 00006.html that describes the sigmoidal contrast algorithm. If your find a problem with our interpretation of the sigmoidal contrast algorithm, let us know.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: possible bug -sigmoidal-contrast IM 6.7.5.7 Q16

Post by fmw42 »

magick wrote:1 means no change. See http://osdir.com/ml/video.image-magick. ... 00006.html that describes the sigmoidal contrast algorithm. If your find a problem with our interpretation of the sigmoidal contrast algorithm, let us know.
Using IM sigmoidal contrast with 1, I do not get no change.

convert rose: -sigmoidal-contrast 1,50% rose_sigm1x50.png
compare -metric rmse rose: rose_sigm1x50.png null:
228.286 (0.00348342)

However, with a smaller value between 0.1 and 0.00001, I then get no change.

convert rose: -sigmoidal-contrast 0.1,50% rose_sigm_0p1x50.png
compare -metric rmse rose: rose_sigm_0p1x50.png null:
0 (0)

convert rose: -sigmoidal-contrast 0.00001,50% rose_sigm0p00001x50.png
compare -metric rmse rose: rose_sigm0p00001x50.png null:
0 (0)

I believe from my experiments (with plotting profiles of a gradient) that for IM sigmodal-contrast with X,Y% as X gets smaller (X>0) approaching zero, the result approaches no change (slope=1), but apparently degenerates to zero slope at x==0 or very very close to it (as X=quantumscale is still bad).

1x50%
Image

convert -size 1x256 gradient: -rotate 90 grad.png
convert -size 1x256 gradient: -rotate 90 -sigmoidal-contrast 1,50% grad_sigm_1x50.png
compare -metric rmse grad.png grad_sigm_1x50.png null:
185.763 (0.00283456) -> approx. 3% error


0.1x50%
Image

convert -size 1x256 gradient: -rotate 90 -sigmoidal-contrast 0.1,50% grad_sigm_0p1x50.png
compare -metric rmse grad.png grad_sigm_0p1x50.png null:
1.9685 (3.00374e-05) -> approx. 0.003% error

0.00001x50%
Image

convert -size 1x256 gradient: -rotate 90 -sigmoidal-contrast 0.0001,50% grad_sigm_0p00001x50.png
compare -metric rmse grad.png grad_sigm_0p00001x50.png null:
0.707107 (1.07898e-05) -> approx. 0.001% error

0x50%
Image

convert -size 1x256 gradient: -rotate 90 -sigmoidal-contrast 0,50% grad_sigm_0x50.png
compare -metric rmse grad.png grad_sigm_0x50.png null:
37873.7 (0.577916) -> approx 58% error
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: possible bug -sigmoidal-contrast IM 6.7.5.7 Q16

Post by magick »

ImageMagick has a number of techniques for speeding up certain algorithms. For many of the image enhancement algorithms (e.g. sigmoidal contrast, gamma, etc), we map the results to a small array of 65536 values which may account for why small changes shows the quantization steps. If instead you;re looking for more accurate values, we can compute the contrast for each pixel value rather than using the acceleration technique. Is that your preference? Trade speed for accuracy for this algorithm? If so, let us know and we will add a patch to the ImageMagick trunk.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: possible bug -sigmoidal-contrast IM 6.7.5.7 Q16

Post by fmw42 »

magick wrote:ImageMagick has a number of techniques for speeding up certain algorithms. For many of the image enhancement algorithms (e.g. sigmoidal contrast, gamma, etc), we map the results to a small array of 65536 values which may account for why small changes shows the quantization steps. If instead you;re looking for more accurate values, we can compute the contrast for each pixel value rather than using the acceleration technique. Is that your preference? Trade speed for accuracy for this algorithm? If so, let us know and we will add a patch to the ImageMagick trunk.

I understand the lookup table approach (and use that approach in a number of my scripts for complicated mathematical expressions). However, I do not think that is the issue that I am trying to explain.

My issue is that there seems to be some degeneration of the sigmoidal-contrast function when X in X,Y% is smaller that some minimum around 0.00001. In principle, I think that the concept should produce no change (slope of 1) as X approaches 0. However, it may be that the mathematical function degenerates to slope=0 when X is exactly zero. The fact that it degenerates for X below about 0.00001 but non-zero may be simply a precision issue or due to the lookup table approach.

But my question is whether the code should be adjusted to make the function skip computation for X less than some minimum by adding an if test such that if x<some min value, then output=input. Or if one should just change the documentation to explain the degeneracy. A value of x=0.00001, seems to be close enough rmse error-wise to consider it no change.

The degeneracy is confirmed using -fx expression according to your link above.

b=10
a=0.5
convert -size 1x256 gradient: -rotate 90 -fx "(1/(1+exp($b*($a-u))) - 1/(1+exp($b*$a))) / (1/(1+exp($b*($a-1))) - (1/(1+exp($b*$a))))" sigm_${b}x50.png
im_profile -s sigm_${b}x50.png sigm_${b}x50_profile.gif
convert -size 1x256 gradient: -rotate 90 grad.png
compare -metric rmse grad.png sigm_${b}x50.png sigm_${b}x50_profile.gif null:
8559.44 (0.130609)

Image



b=1
a=0.5
convert -size 1x256 gradient: -rotate 90 -fx "(1/(1+exp($b*($a-u))) - 1/(1+exp($b*$a))) / (1/(1+exp($b*($a-1))) - (1/(1+exp($b*$a))))" sigm_${b}x50.png
im_profile -s sigm_${b}x50.png sigm_${b}x50_profile.gif
convert -size 1x256 gradient: -rotate 90 grad.png
compare -metric rmse grad.png sigm_${b}x50.png sigm_${b}x50_profile.gif null:
185.701 (0.00283361)

Image


b=0.00001
a=0.5
convert -size 1x256 gradient: -rotate 90 -fx "(1/(1+exp($b*($a-u))) - 1/(1+exp($b*$a))) / (1/(1+exp($b*($a-1))) - (1/(1+exp($b*$a))))" sigm_${b}x50.png
im_profile -s sigm_${b}x50.png sigm_${b}x50_profile.gif
convert -size 1x256 gradient: -rotate 90 grad.png
compare -metric rmse grad.png sigm_${b}x50.png sigm_${b}x50_profile.gif null:
0 (0)

Image

b=0
a=0.5
convert -size 1x256 gradient: -rotate 90 -fx "(1/(1+exp($b*($a-u))) - 1/(1+exp($b*$a))) / (1/(1+exp($b*($a-1))) - (1/(1+exp($b*$a))))" sigm_${b}x50.png
convert: divide by zero `(1/(1+exp(0*(0.5-1.0*u)))-1.0*1/(1+exp(0*0.5)))/(1/(1+exp(0*(0.5-1.0*1)))-1.0*(1/(1+exp(0*0.5))))' @ error/fx.c/FxEvaluateSubexpression/2138.

Mathematically, the b=0 case does degenerate as it has a divide by zero as the last two terms for the over all denominator cancel each other (1/2-1/2=0) when b=0
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: possible bug -sigmoidal-contrast IM 6.7.5.7 Q16

Post by fmw42 »

Magick or Anthony,

Any comments on my last post above?

Fred
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: possible bug -sigmoidal-contrast IM 6.7.5.7 Q16

Post by anthony »

UPDATE...

I am not surprised by the b=0 result.

Really the function is designed to scale the result so it goes between points 0,0 and 1,1 when b=0 the function becomes a constant and that scaling will simply not work. When b=(almost zero) the function is not quite constant and the scaling, no matter how much scaling it has to apply, has some vertical difference to work with.

Really any value less than b=1 (a linear result) is nonsensical, due to the auto-scaling.

Strangely a value of b=(near infinitity) is sensible! It is a near threshold.
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: possible bug -sigmoidal-contrast IM 6.7.5.7 Q16

Post by fmw42 »

Really any value less than b=1 (a linear result) is nonsensical, due to the auto-scaling.
I disagree. It is both mathematically and practically perfectly fine to have values less than 1, just so long as it is not so very small that it is essentially zero due to the quantization used by the look-up table. From my results above, values down to 0.00001 work perfectly fine and produce very small (fraction of a percent) or zero rmse error.

So the issue is whether to modify the function so that it no-ops for values less than 0.00001 or change the docs to explain the degeneracy and suggest a minimum practical value of 0.00001
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: possible bug -sigmoidal-contrast IM 6.7.5.7 Q16

Post by anthony »

fmw42 wrote:
Really any value less than b=1 (a linear result) is nonsensical, due to the auto-scaling.
I disagree. It is both mathematically and practically perfectly fine to have values less than 1, just so long as it is not so very small that it is essentially zero due to the quantization used by the look-up table. From my results above, values down to 0.00001 work perfectly fine and produce very small (fraction of a percent) or zero rmse error.
What would you use it for? Yes it isn't quite a no-op but not by very much.

If the auto-scaling was disabled for values less than b=1.0 then maybe it could have some practical use. But it isn't what it was designed for.

My own thinking is to either leave it alone and document the impracticality of values less than 1,
OR set b=1 if given b is less than 1. (a bit like what is now done for values of sigma=0 for blurs).
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: possible bug -sigmoidal-contrast IM 6.7.5.7 Q16

Post by fmw42 »

What would you use it for? Yes it isn't quite a no-op but not by very much.
When scripting if the user supplies zero, then no sigmoidal-contrast is applied, but if non-zero, then it is used. So a no-op condition is useful.

Yes, I know I can trap it out and skip over the sigmoidal-contrast. But it seems to be an inconsistency that I do not in general like. This is a bit of nit-picking, but either I can explain the degeneracy in the docs and do my own script trapping or it could be trapped at 0.00001 in the code and made a no-op.

Besides a value of 1 is not really close enough. It leave about 3% error as I mentioned above. Whereas a value of 0.00001 is a very small fractional % error from the no-op. I certainly do not want a value of 1 to be set to no-op. But I can see where a value of 0.00001 is negligible difference and so anything lower could be considered as no-op.

I am not sure what you mean by auto scaling? What does that have to do with sigmoidal-contrast?


Anyway, lets just close this topic. I will edit the docs to explain the degeneracy. You guys are too busy to deal with this minor issue.
Post Reply