Author Topic: New JavaScript runtime methods: Image.morphologicalTransform() and Image.convolveFFT()  (Read 8123 times)

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
The latest build 341 of the PixInsight core application adds two new methods and a static property to the Image core JavaScript object. These additions address pure image processing tasks.

=========================================================

void Image.morphologicalTransform( int operator, Array structure[, Number thr0=0[, Number thr1=0[, int interlacingDist=1]]] )

This method applies a morphological transform with the specified morphological operator and structure structuring element.

operator

Specifies the morphological operator to apply. Valid values are defined in the <pjsr/MorphOp.jsh> include file as follows:

Code: [Select]
#define MorphOp_Erosion    0  // Erosion operator
#define MorphOp_Dilation   1  // Dilation operator
#define MorphOp_Closing    2  // Closing operator (erosion+dilation)
#define MorphOp_Opening    3  // Opening operator (dilation+erosion)
#define MorphOp_Median     4  // Morphological median
#define MorphOp_Selection  5  // Morphological selection; uses Image.selectionPoint


The morphological selection operator (selectable with MorphOp_Selection) applies a selection algorithm to pick the n-th element from the current set of neighbor pixels sorted in ascending order, as defined by the structuring element. The n-th position is defined by the following property:

Number Image.selectionPoint

in the [0,1] range, where 1 corresponds to the last element in the ordered neighborhood set, and 0 to the first element.

The morphological selection operator is a variable erosion/dilation operator. Note that when Image.selectionPoint is equal to 0.5, the selection operator is exactly the same as the morphological median operator. Correspondingly, when Image.selectionPoint is zero we have a pure erosion operator, and if Image.selectionPoint is one we have a pure dilation operator.

structure

Defines a n-way structuring element of the form:

<way_0>[,<way_1>[, ..., <way_n-1>]]

where <way_i> is an unidimensional array of length NxN that stores the elements of a square matrix of dimension N, such that:

- N is constant for 0 <= i < n
- N is odd

Note that the second condition prescribes the existence of a unique central element in each structure way.

Nonzero array values denote existent, or solid structure elements. Zero array values correspond to nonexistent elements, or holes in the structure.

The structure matrix corresponding to each way, so defined, is used to compute a single value for each pixel neighborhood by applying the specified morphological operator. Then the final result of the transform for each pixel is the arithmetic mean of all partial results.

For example, the following code would apply a standard three-way hybrid (or directional) median filter:

Code: [Select]
#include <pjsr/MorphOp.jsh>
// ...
var foo = new Image;
// ...
foo.morphologicalTransform( MorphOp_Median,
   [[0, 0, 0, 0, 0,
     0, 0, 0, 0, 0,
     0, 0, 1, 0, 0,
     0, 0, 0, 0, 0,
     0, 0, 0, 0, 0], [0, 0, 1, 0, 0,
                      0, 0, 1, 0, 0,
                      1, 1, 0, 1, 1,
                      0, 0, 1, 0, 0,
                      0, 0, 1, 0, 0], [1, 0, 0, 0, 1,
                                       0, 1, 0, 1, 0,
                                       0, 0, 0, 0, 0,
                                       0, 1, 0, 1, 0,
                                       1, 0, 0, 0, 1]] );


Note that we define the multiway structure as an array of arrays in JavaScript syntax. A hybrid median filter preserves edges much better than a square-box median filter because it is a three-step ranking operation where data from different spatial directions are ranked separately. In the example above, the three ways define individual ranking operations for the central pixel, for vertical pixels, and diagonal pixels, respectively.

thr0
thr1

These parameters are, respectively, the low and high thresholds that define a range of values to apply the morphological transform. Let's define the following variables:

f: the original pixel value for the current central structure element.

r: the resulting pixel value that should replace the original one. This results from applying the morphological transform to the current pixel neighborhood with all structure ways.

Then, assuming pixel values in the normalized [0,1] range, the thresholding algorithm is as follows (pseudo-code):

Code: [Select]
if ( r < f )
   k = f - r
   if ( k < thr0 )
      k = k/thr0
      r = k*r + (1 - k)*f
   fi
else
   k = r - f
   if ( k < thr1 )
      k = k/thr1
      r = k*r + (1 - k)*f
   fi
fi


and the resulting value of r replaces f in the final image. The default values are zero, so no thresholding is applied by default.

interlacingDist

This is the interlacing distance >= 1 used to apply the morphological transformation. For example, if the interlacing distance is two we have the following matrix:

Code: [Select]
1 0 1 0 1
0 0 0 0 0
1 0 1 0 1
0 0 0 0 0
1 0 1 0 1


where ones correspond to original pixel values and the zeros are called holes, where the transformation will not be applied. The default value of this parameter is one, that is, there are no holes by default.

This interlacing scheme is the same used in the à trous (with holes) wavelet transform algorithm. It allows to apply a morphological transform at different scales, just as a wavelet transform. So it is quite easy to define multiscale morphological transforms with our implementation.

Spatial convolutions via Image.convolve() are also thresholded and interlaced transforms in the PixInsight JavaScript runtime, in the terms we have just described them here.

=========================================================

void Image.convolveFFT( Array kernel )
void Image.convolveFFT( Image respFunc )


This method applies a spatial convolution with a high-performance algorithm based on fast Fourier transforms. The response function of the convolution can be specified either as a kernel filter or as a grayscale image. For example:

Code: [Select]
var foo = new Image;
var bar = new Image;
// ...
foo.convolveFFT( bar );


and also:

Code: [Select]
var foo = new Image;
// ...
foo.convolveFFT( [0, 1, 2, 1, 0,
                  1, 2, 4, 2, 1,
                  2, 4, 8, 4, 2,
                  1, 2, 4, 2, 1,
                  0, 1, 2, 1, 0] );


In the second case (kernel filter), the square root of the array length must be an odd integer, so that there exists a single central element in the square filter matrix. Other than this restriction (which does not apply in the case of an image used as the response function), the images can have arbitrary sizes, only limited by the available memory.

To apply kernel filters of sizes below 17x17, it is more efficient to use Image.convolve(), which applies a direct convolution in the spatial domain. Image.convolve() is also a thresholded/interlaced transform, just as Image.morphologicalTransform() (see the preceding section).
Juan Conejero
PixInsight Development Team
http://pixinsight.com/