Accuracy problems with -evaluate, -fx, -function

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?".
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Accuracy problems with -evaluate, -fx, -function

Post by fmw42 »

Perhaps I misunderstand, but what is the point of -fx "log(u)" if it always returns zero for every value in the image. I guess one needs to do proper scaling such as done in -evaluate log. I think when I used this in my script I did -fx "log(u+1)" and that produced values that were more linear than log as you point out about log(1)=0 and log(2)=.3 I was mis-remembering about adding +1 and thought that IM did that internally.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Accuracy problems with -evaluate, -fx, -function

Post by anthony »

The point is that it is just a mathematical function, as defined by the standard math library common to all computers. You need to adjust your values and apply the appropriate formula to use it! Not only the input range but also perhaps the output range, offsets, and in the case of log() the base you want.

For example the log function is often used to determine the number of digits needed to hold a number.
For example a value of 1023 at base 2 needs 10 bits (1's and 0's), as value of 1024 needs 11 bits.

Heres the calculation for the number of digits those numbers needs!

Code: Select all

convert null: -format '%[fx:floor(log(1023)/log(2)+1)]' info:
10
convert null: -format '%[fx:floor(log(1023)/log(2)+1)]' info:
11
How about a 16 bit image value, in base 10 say the green component of the color dodgerblue.

Code: Select all

convert xc:dodgerblue -format 'green value of %[fx:g*(2^16-1)] has %[fx:floor(log(g*(2^16-1))/log(10)+1)] digits' info:
green value of 37008 has 5 digits
In IMv7 I hope to allow you store and re-use fx values in later expressions :-) whcih will save some processing in the above.

As you can see log() is very useful!
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: Accuracy problems with -evaluate, -fx, -function

Post by fmw42 »

I know the log is useful, but using -fx "log(u)" is non-useful when u ranges from 0 to 1. I believe that is the point of the whole topic -- normalized image values rather than processing the actual image values. So I was just pointing out a rather unusual situation with the log() and normalized values.

I understand that normalization is the basis of the way IM handles things. But as I said before, it would be nice to have an optional compile that did not do this, though I doubt that will happen, because it will be so much different than the existing code. But it is worth at least a discussion for IM 7.

I believe other systems, such as ImageJ, do it without normalizing, though may restrict the image to grayscale for some functions. The TRW system I used many years ago also did it without normalizing. The downside is that one has to change the bit-depth of the resulting images depending upon the processing. In that system, we had 8-bit images and full floating point images. Some functions would preserve the 8-bit results, but many others resulted in 32-bit per channel images (though probably limited to grayscale).

So one has to decide to trade the flexibility of normalizing, its memory benefits when limited to Q8 (or Q16) with its at times inexact mathematics vs the limited data types for given functions when doing full 32-bit processing results.

Seems to me that IM has chosen the better approach, though at times I would like to have it the other way.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Accuracy problems with -evaluate, -fx, -function

Post by anthony »

Actually most operators in IM does not do normalization. Most compose methods don't, but then most will work for any range of values.

I am sure however that if this is really a problem then some option can be arranged, but the question is what operators should that option would effect? and to what extent?
Any problem in computer science can be solved
with one more level of indirection. --- Morven's Metatheorum
...But will usually create another layer of problems. -- unknown
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: Accuracy problems with -evaluate, -fx, -function

Post by fmw42 »

I thought they all did? Is there a list of which ones normalize?
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Accuracy problems with -evaluate, -fx, -function

Post by anthony »

fmw42 wrote:I thought they all did? Is there a list of which ones normalize?
Actually they typically deal with the numbers as best they can, to achieve the defined composition. For example "Plus" has no range problems at all. It works as long as both values are in the same range, normalized or otherwise.

More typically with a sprinkling of QuantumRange values is used as necessary to achieve the defined result. For example compose "Multiply" is defined as a multiply of Src and Dst using image values which are normalized (typically making images darker, or a "burning" lighting effect). But instead of normalizing the values it simply does Src*Dst*QuantumScale (where QuantumScale = 1/QuantumRange as multiplys are generally faster than divides).

It is actually a lot more complicated than that due to the default use of "Over" Alpha Blending of the images when alpha channel is involved (and the channel 'sync' flag is enabled). See the SVG composition specifications for details of that complexity. But basically that is how it works internally to achieve the defined result in the most optimal way.

I spent a lot of time on these optimizations and understanding how to apply the alpha blending and test to ensure I was getting correct results, as defined by the SVG specification. The use of the 'sync' flag to enable/disable 'alpha blending' effects, was an important addition, though likely to be different in IMv7.

Specifically avoiding normalization as part of the operators optimization.

The same thing happens in convolutions, where the weighted averaging of values make the actual range of the values being used of little consequence, alpha weighting or otherwise.

Actually there is a current bug in that if you use a non-normalized kernel with a image containing alpha, the alpha weighting normalization also ends up normalizing the convolution kernel results as well! I discovered this by accident, and spend some time tracking down the problem as for that example I actually did not want the kernel normalized!
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: Accuracy problems with -evaluate, -fx, -function

Post by fmw42 »

what other functions require normalization besides -fx? Does -evaluate? What else? You make it sound like most of IM does not normalize, but I thought it was the other way.
alosca
Posts: 52
Joined: 2010-03-04T17:54:57-07:00
Authentication code: 8675308
Location: Pasadena, California

Re: Accuracy problems with -evaluate, -fx, -function

Post by alosca »

I disagree with the assertion

"The same thing happens in convolutions, where the weighted averaging of values make the actual range of the values being used of little consequence, alpha weighting or otherwise."

This was exactly the problem I reported at the beginning of this thread, when multiplications used in a convolution computation I was doing were giving me wrong results, and the culprit was the [0,1] normalization AND the way things are internally computed in IM, out of user control. So it does matter which range you use for pixel values. The numerics of integers is way way different than the numerics of real/floating point numbers.

I like IM a lot and I will continue using it even though it has its limits. The -evaluate pow does not work, i.e. it does not produce expected results, as well as other functions, log, add, abs, etc. Without trying to be repetitive, if I give you an image with 9 for pixel values I want -evaluate pow 2 to always return 81, independent of the internal representation used in IM. I want 81 because this is the right number, I gave a pair of 9s to pow, IM must give me 81.

Now, if you say up front that my 9s will be converted to floats 9/255 = 0.0352941176471, and that I should expect computations to be done with that representation, then I will be on alert. But since normalization is not always used, what should I expect from computations? Sometimes things are not as clear as they should:

convert -size 1x1 xc:"gray(9)" -depth 8 -evaluate multiply 9 txt:
# ImageMagick pixel enumeration: 1,1,255,rgb
0,0: ( 81, 81, 81) #515151 rgb(81,81,81)

planta [171] : convert -size 1x1 xc:"gray(9)" -depth 8 -evaluate pow 2 txt:
# ImageMagick pixel enumeration: 1,1,255,rgb
0,0: ( 0, 0, 0) #000000 rgb(0,0,0)

I know now where the problem resides, but this is not really transparent. From now on I should use -fx instead of -evaluate with the proper scaling in place, i.e.

convert -size 1x1 xc:"gray(9)" -depth 8 -format "%[fx:(u*255)*(u*255)]" info:
81

The price to pay is in speed and more typing.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Accuracy problems with -evaluate, -fx, -function

Post by fmw42 »

You can do this also, but it is a similar issue (and function dependent regarding the multiplier):

convert -size 1x1 xc:"gray(9)" -evaluate pow 2 -evaluate multiply 255 -depth 8 txt:
# ImageMagick pixel enumeration: 1,1,255,rgb
0,0: ( 81, 81, 81) #515151 rgb(81,81,81)
Post Reply