BandMathX: combination of neighborhood and scalar operations

Hi,
I am trying to implement a pixel-wise operation with BandMathX. Let’s say we have a one-dimensional image X, I want to compute for every pixel

\frac{( x_i - \bar{x} ) \sum_{j \in N_i} (x_j - \bar{x} )}{\sigma^2_x }

where x_i is the pixel to be processed, \bar{x} is the mean value of X, N_i is the neighborhood of x_i (e.g., a square window of size 3x3), j \in N_i is the neighbors of x_i and \sigma^2_{x} is the variance of the image.

In order to use BandMathX, the expression can be written like this:

|N_i|\frac{( x_i - \bar{x} )(\bar{x}_i - \bar{x})}{\sigma^2_x }

where |N_i| is the number of neighbors of x_i and \bar{x}_i is the local mean in the neighborhood of x_i.

If we consider a square window of size 3, I have tried the following expression (among others …):

9 * (im1b1 - im1b1Mean) * (mean(im1b1N3x3) - im1b1Mean) / im1b1Var

But I got this error

RuntimeError: Exception thrown in otbApplication Application_Execute: /home/mfauvel/Iota2InstallDir/iota2/scripts/install/OTB/OTB/Modules/Filtering/MathParserX/src/otbParserX.cxx:235:
itk::ERROR: ParserXImpl(0x12d7400): 
Message:     Can't evaluate function/operator "-": Argument 1 of function/operator "-" is of type 'm' whereas type 'c' was expected.
Formula:     9 * (im1b1 - im1b1Mean) * (mean(im1b1N3x3) - im1b1Mean) / im1b1Var
Token:       -
Position:    43

I understand that mean(im1b13x3) is not of the same type than im1b1Mean. I read the cookbook and I don’t see where I am wrong.

After several tries, I suspect that mean(im1b1N3x3) cannot be used in combination with scalar operation.

So my question: is it possible to perform such operation in one pass ? I can pre-compute the local mean, but it’s less elegant :frowning:

Mathieu

Hello,

the output of mean(im1b1N3x3) is a vector of dimension 1, which is different from a scalar in BandMathX ( mean(im1b1N3x3, im1b2N3x3) would output a vector of dimension 2). It is not possible to subtract a scalar to a vector.

This means that you either have to convert mean(im1b1N3x3) to a scalar or im1b1Mean to a vector.

In your case you can write:

9 * (im1b1 - im1b1Mean) * (mean(im1b1N3x3)[0] - im1b1Mean) / im1b1Var

the [ ] operator takes the first element of a vector.

Alternatively,

9 * (im1b1 - im1b1Mean) * (mean(im1b1N3x3) - {im1b1Mean}) dv im1b1Var

the {s1, s2, ... sn} operator convert n scalars into a n-dimensional vector.

note the use of dv that performs division of a vector by a scalar value.

Cédric

1 Like

Dear Cedric,

Thank you for the explanation. I use the fist option and it works well.

Mathieu