Author Topic: [PixelMath Q] What I'm doing wrong?  (Read 6476 times)

Offline Yuriy Toropin

  • PixInsight Addict
  • ***
  • Posts: 209
[PixelMath Q] What I'm doing wrong?
« on: 2010 January 02 07:00:54 »
Hi,
Will appreciate if anybody will comment on what am I doing wrong?
I have 4 grayscale images available, L, R, G, B

First, I combine from them RGB image with the following expressions in each channel (literally speaking, it's L*(R||G||B)/(R+G+B), with some channel normalization):
R
Code: [Select]
(L-min(L))/(max(L)-min(L))/
((R-min(R))/(max(R)-min(R))+(G-min(G))/(max(G)-min(G))+(B-min(B))/(max(B)-min(B)))*
(R-min(R))/(max(R)-min(R))
and the same for G and B channels with R in the last line replaced with G and B respectively.

This approach works fine and at the end I'm getting RGB image stretched following L, with data in all 3 channels, R,G,B.

After that I'm trying to apply some logic, define symbols k_col=2.5, SR,SG,SB, and change expressions in channels to (only R one is presented):
Code: [Select]
SR=(L-min(L))/(max(L)-min(L))/
((R-min(R))/(max(R)-min(R))+(G-min(G))/(max(G)-min(G))+(B-min(B))/(max(B)-min(B)))*
(R-min(R))/(max(R)-min(R))*k_col;
iif(SR>1,1,SR)
Expressions for G and B are the same with bold R in 1st, 3rd, and 4th lines replaced by G and B.

In this case after execution I've got color image in which only R channel is calculated right, G and B are all zeros.

There is no mistypes in my expressions, attached is related PSM file... This behavior will be reproduced in case if formulae is presented for each channel, and it is "complicated", in other word, consists of more than 1 expression with use of some local symbols.

What am I doing wrong? How to get data in all 3 channels using non-trivial expressions (consists of more than one expression) in channel formulae?

Thanks a lot for your help,
     Yuriy
« Last Edit: 2010 January 02 10:07:06 by Yuriy Toropin »

Offline Niall Saunders

  • PTeam Member
  • PixInsight Jedi Knight
  • *****
  • Posts: 1456
  • We have cookies? Where ?
Re: [PixelMath Q] What I'm doing wrong?
« Reply #1 on: 2010 January 02 09:34:22 »
Hi Yuriy,

Before I get a chance to fully analyse your PixelMath problem, my immediate thought was to a 'bug' that I reported a few weeks back, and which Juan then confirmed.

You can see the message exchange here
http://pixinsight.com/forum/index.php?topic=1586.0

I will find time to check out your scenario later tonight.

Regards,
Cheers,
Niall Saunders
Clinterty Observatories
Aberdeen, UK

Altair Astro GSO 10" f/8 Ritchey Chrétien CF OTA on EQ8 mount with homebrew 3D Balance and Pier
Moonfish ED80 APO & Celestron Omni XLT 120
QHY10 CCD & QHY5L-II Colour
9mm TS-OAG and Meade DSI-IIC

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: [PixelMath Q] What I'm doing wrong?
« Reply #2 on: 2010 January 05 15:11:38 »
Yuriy,

Your expressions work fine with the new version of PixelMath, which fixes the bug discovered by Niall, along with a few others affecting the iif(), min(), max() and other similar functions.

The new version of this tool will be released soon, along with an improved version of StarAlignment.

Thank you for your help, and sorry for the inconvenience.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Yuriy Toropin

  • PixInsight Addict
  • ***
  • Posts: 209
Re: [PixelMath Q] What I'm doing wrong?
« Reply #3 on: 2010 January 07 11:36:09 »
The new version of this tool will be released soon, along with an improved version of StarAlignment.
Thanks, Juan, looking forward for it!

Another issue - tutorials on PixelMath tell that "local" variables declared "inline" are allowed, while in recent version of PixelMath it's not the case, any variables should be defined in "symbols" in advance (again, see example above). It doesn't make any sense 'cause PixelMath is "interpretator" with late binding, not "compilator", if I understand its concept correctly.

Could ability to introduce variables "inline" be restored together with other fixes? It's just more convinient and natural way of writing expressions.

Thanks a lot for all your support,
   Yuriy

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: [PixelMath Q] What I'm doing wrong?
« Reply #4 on: 2010 January 07 14:37:28 »
Quote
PixelMath is "interpretator" with late binding, not "compilator",

Not exactly. PixelMath pre-evaluates and optimizes some critical parts of the expressions prior to execution. Expression pre-evaluation and optimization force early binding and strong type checking in PixelMath, in a way quite similar to C++. In particular, PixelMath knows in advance where all references to images and variables are in the expressions before they are executed, and optimizes the generated p-code consequently. This is why PixelMath can usually run much faster than equivalent JavaScript code.

In addition, as PixelMath is fully multithreaded, all variables must be reflected on thread-local data (TLD) structures before execution, in order to prevent concurrent write operations, and hence to minimize thread locks.

For the reasons above, declaring variables is absolutely necessary in PixelMath, just as it is in compiled languages such as C, C++, FORTRAN or Pascal.

Quote
tutorials on PixelMath tell that "local" variables declared "inline" are allowed

Sorry if I've given that impression. In a PixelMath expression such as:

foo = bar;

it is undetermined whether "bar" refers to an image or to a variable/constant. Note that even if there exists a "bar" image, you could define a "bar" variable in your PixelMath instance, which would always take precedence over the image. So if "bar" has not been defined as a symbol, it is interpreted as a reference to an image by default.

On the other hand, "foo" could be automatically interpreted as a reference to a variable, a la JavaScript for example, as it is clearly playing the role of an lvalue (left-hand value) in the expression. However, I took the decision to disallow these semantic constructs for several reasons. Two very important ones are:

- Automatic variable generation prevents using images as lvalues. Currently this is not possible, but future versions of PixelMath could allow direct assignments to images (a single PixelMath expression could then modify several images).

- If images can play lvalue roles in PixelMath expressions, automatic variable generation implies that the above PixelMath expression would behave differently depending on whether a "foo" image exists or not. This violates PixInsight's object oriented design principles.

Hope this clarifies.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Yuriy Toropin

  • PixInsight Addict
  • ***
  • Posts: 209
Re: [PixelMath Q] What I'm doing wrong?
« Reply #5 on: 2010 January 08 00:14:23 »
Thanks for clarification, Juan, your points make real sense!

I'm referening to these lines in PixelMath Reference  
  • Variables. User-defined symbols can be declared as temporary variables. This allows to store intermediate results, and is especially useful when combined with multiple statements (see next point).
  • Multiple statements. A PixelMath expression can include multiple statements to perform temporary calculations that can be assigned to variables. This greatly improves execution performance and facilitates writing very complex expressions.

Previously I thought that it's possible to have temporary image (variable) and use it as lvalue, like in this code
Code: [Select]
SR=(L-min(L))/(max(L)-min(L))/...
iif(SR>1,1,SR)
...

Is this code semantically correct?
How recent fixed version of PixelMath will interpret it, will SR be a temporary image (looks like - it will not) OR it will be a float value refering to recent pixel of image under processing, like SR = Img(PixelX, PixelY, ChannelZ)?

Looks like I have to switch to JavaScripts from PixelMath...

Thanks a lot for your help and sorry for all those misunderstanding and questions,
   Yuriy

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: [PixelMath Q] What I'm doing wrong?
« Reply #6 on: 2010 January 08 01:30:46 »
Hi Yuriy,

Indeed the Pixelmath reference document is obsolete (as are so many...) and requires a thorough revision. I'll try to state things clearer with more and better examples.

Quote
Previously I thought that it's possible to have temporary image (variable) and use it as lvalue, like in this code
Code:
SR=(L-min(L))/(max(L)-min(L))/...
iif(SR>1,1,SR)
...
Is this code semantically correct?

And it is possible, but all variables must be defined as symbols in the PixelMath instance. The above code is syntactically correct. However the final expression, namely:

Code: [Select]
iif( SR>1, 1, SR )
is redundant when the Rescale result option is disabled, as is the case with your instances. The reason is that when Rescale result is disabled, PixelMath already constrains output values to stay within the normalized [0,1] range by truncation, as necessary. So your expressions don't need SR, SG and SB variables as you just need to execute them without any assignment:

Code: [Select]
(L-min(L))/(max(L)-min(L))/...
and so on.

As a side note, there are simpler alternatives to the above expression, such as for example:

Code: [Select]
min( SR, 1 )
which is faster because it avoids the branching logic inherent to iif().
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Yuriy Toropin

  • PixInsight Addict
  • ***
  • Posts: 209
Re: [PixelMath Q] What I'm doing wrong?
« Reply #7 on: 2010 January 08 04:03:28 »
Thanks a lot, Juan, got it!
...
Meantime, have found the "native PI way of doing things" via using Channel Extraction/Combination in HSI mode with substituting of I(ntensity) channel with desired (stretched) one ;)
...

Out of topic, suggestion for PI improvements:

Is it possible to add "blending" coefficient to Intensity transformation processes like Histogram and Curve.

Let KBlend will be the coefficient, [0;1] or [0%;100%] (slider),
   ImgInit - initial image
   ImgIntTrans=f(ImgInit) - result of Intensity Transformation,
then the final result of Image Transform application will be equal to
   ImgIntTransFinal=(1-KBlend)*ImgInit + KBlend*ImgIntTrans,
that will somewhat mimic "Opacity" and "Fill" properties of channels in PhotoShop, for ex.

Otherwise, I often mix "initial" and "transformed" image via pixelmath, but it lacks preview functionality.