Pixel Math
 The PixelMath Process Target Image and Operands Operators NOP — No operation ADD — Addition SUB — Subtraction MUL — Multiplication DIV — Division DIV* — Division with constrained infinity POW — Power (exponentiation) DIF — Absolute difference MIN — Minimum value MAX — Maximum value MOV — Move (copy) pixels OR — Bitwise Logical OR AND — Bitwise Logical AND XOR — Bitwise Logical XOR Result Options Channel Coefficients Additive Constant Rescale Inversion Features and Limitations The amount of images that can be operated with a single instance of PixelMath Parenthesized expressions Sizes of operand images Operating between color and grayscale images The accuracy of intermediate calculations The accuracy of rescale operations How bitwise logical operations are calculated When the target image is also used as an operand Using PixelMath with preview objects The Pixel Math Window Source Operands list box Current Operand Parameters controls Operator combo box Operand combo box Channel Coefficient edit controls Invert check box Reset Channel Coefficients / Inversion button Move Operand buttons New button Delete button Clear button Result Parameters controls Channel Coefficient edit controls Add Constant edit control Invert check box Rescale check box / edit Destination Parameters controls Replace Target radio button The PixelMath Process PixInsight's PixelMath performs a series of pixel-level arithmetic and logical operations between images. For example, suppose four images of the same object, identified as A, B, C, D. Once properly aligned, a common operation is averaging them to increase the signal-to-noise ratio of the resulting stacked image: (A + B + C + D) / 4 The above averaging formula is applied to each pixel of the four-pixel stack. PixelMath can perform the above expression very easily in a single operation —in fact, PixelMath is able to do many complex and interesting things. The applications of PixelMath are numerous and important in all fields of technical image processing: image integration and composition, mask generation, correction of uneven illumination (application of flat fielding, vignetting or gradient correction masks), just to mention some well-known examples. Basically, an instance of PixelMath contains a set of references to operand images, the operations that must be performed between them, and some parameters to control how the result image is generated. Target Image and Operands The image an instance of PixelMath is applied to is called the target image of the process. From PixelMath's point of view, the target image is just a placeholder variable: it is unknown until the process instance is executed, so it isn't included as an actual parameter. The rest of elements that participate in the expression being calculated are operands. Operands can be either images or constant values. For example, if you want to subtract the image identified as 'Image01' from any target image, the required PixelMath instance could be represented as: <*target*> SUB Image01 where: <*target*> identifies the target image, which is unknown until execution. SUB stands for the subtraction operator. Image01 is the identifier of an operand image. When no image is used for an operand, a different constant value is used for each channel of the target image. For example, if the target is a RGB color image, a PixelMath instance like: <*target*> MUL (0.95, 1.00, 0.98) might be used to apply a linear color correction to the target image. MUL stands for the multiplication operator. For grayscale images, a single constant is used. In addition, target and operand images can be inverted. Inversion always takes place before the operations associated to operands. If p is a target or operand pixel, and inversion has been selected for the target or the corresponding operand image, then p' ¬ 1 — p where p' is the inverted pixel used to operate. Operators Let's identify a target image as T, and an operand, either an image or a set of numerical constants, as P. Then the following operators are supported in PixInsight LE 1.0: NOP — No operation This operator does just nothing. It is included mainly for formal reasons. When an operand has been assigned this operator, it is simply ignored. This can be useful to temporarily disable an operand without having to remove it from the PixelMath instance. ADD — Addition Operand pixels or values are added to target pixels: T ¬ T + P SUB — Subtraction Operand pixels or values are subtracted from target pixels: T ¬ T – P MUL — Multiplication Target pixels are multiplied by operand pixels or values: T ¬ T × P DIV — Division Target pixels are divided by operand pixels or values: T ¬ T / P When an operand pixel or value is less than 1.0×10–35 in absolute value, an effective division by zero is assumed. The resulting target pixel is given the largest possible numerical value in the range of IEEE 32-bit floating point, that is, 3.4×10+38, with the same sign as the target pixel value (the sign of the operand is ignored in this case). Note that if some division by zero occurs and the rescale result option is selected, the resulting image will probably be unusable, since the available dynamic range will first be extended to +/-3.4×10+38 in order to keep all of the existing data, then pixel values will be rescaled to the specified range, and finally to the normalized [0,1] range, if necessary. In these cases, actual image data is constrained to a tiny effective range of numerical values, which leads to a severe loss of accuracy. DIV* — Division with constrained infinity This operator is equivalent to the normal division DIV operator. However, if the rescale result option is selected and there are divisions by zero, the problem mentioned for the DIV operator does not occur with DIV*. To avoid severe loss of numerical accuracy due to infinities generated in divisions by zero operands, all of the resulting infinity pixel values are discarded by plain truncation to the specified rescaling range. Then, pixel values are rescaled to the specified range, and finally to the normalized [0,1] range, if necessary. The neat result is that infinities result in pure white (or black, if negative pixel values were generated by PixelMath operations), and the rest of the image is the result of a normal division, with an optimal usage of the full available dynamic range. POW — Power (exponentiation) Target pixels are raised to operand pixels or values: T ¬ TP DIF — Absolute difference Target pixels are replaced with the absolute values of their differences with operand pixels or values: T ¬ |T – P| MIN — Minimum value Target pixels are replaced with operand pixels or values, only if the operand is less than the target: T ¬ Min( T, P ) MAX — Maximum value Target pixels are replaced with operand pixels or values, only if the operand is greater than the target: T ¬ Max( T, P ) MOV — Move (copy) pixels Target pixels are replaced with operand pixels or values: T ¬ P OR — Bitwise Logical OR Target pixels are bitwise-ORed with operand pixels or values: T ¬ T or P The bitwise logical OR operation works between two integer numbers at the bit level. For each single bits t, p of the result pixel and the operand, respectively, t or p ® 0 if t = 0 and p = 0 1 if t = 1 or p = 1 See a specific section on this document to learn how bitwise logical operators are calculated by PixelMath. AND — Bitwise Logical AND Target pixels are bitwise-ANDed with operand pixels: T ¬ T and P The bitwise logical AND operation works between two integer numbers at the bit level. For each single bits t, p of the result pixel and the operand, respectively, t and p ® 1 if t = 1 and p = 1 0 if t = 0 or p = 0 See a specific section on this document to learn how bitwise logical operators are calculated by PixelMath. XOR — Bitwise Logical XOR Target pixels are bitwise-XORed with operand pixels: T ¬ T xor P The bitwise logical XOR operation works between two integer numbers at the bit level. For each single bits t, p of the result pixel and the operand, respectively, t xor p ® 1 if t ¹ p 0 if t = p See a specific section on this document to learn how bitwise logical operators are calculated by PixelMath. Result Options The resulting image can be modified by the following optional parameters: Channel Coefficients Each channel of the result image can be multiplied by a constant value. This is mainly used to apply linear color corrections to RGB color images. Additive Constant A unique constant value can be added to all channels of the resulting image. Rescale When no rescaling is selected, resulting pixels are just truncated to the normalized range. For each pixel r of the result: r' ¬ Min(Max(0, r), 1) where r' represents the truncated resulting pixel value. If the Rescale option is selected, then the resulting pixels are first rescaled to the normalized [0,1] range. This is done by: r' ¬ (r — m) / (M — m) where r' is the normalized pixel value. m and M are, respectively, the minimum and maximum pixel values in the resulting image prior rescaling, such that m < M. If the result is filled with a constant value, i.e. if m = M, then all result pixels are replaced by the truncating expression: r' ¬ Min(Max(0, m), 1) and no more rescaling is done. When m < M, a numerical range, distinct from the normalized range, can be specified to rescale the resulting image. If [a, b] denotes the user-specified rescaling range, such that a < b, a ³ 0, and b £ 1, then an additional rescaling operation is applied: r'' ¬ (r' — a) / (b — a) Where r'' is the resulting pixel rescaled to the user-specified range. Inversion Optionally, the resulting image can be inverted, that is, for each pixel r of the result: r' ¬ 1 — r is the inverted result in the normalized [0,1] range. Inversion is always done after rescaling, when applicable. Features and Limitations The amount of images that can be operated with a single instance of PixelMath PixelMath can take an unlimited number of operands. When operand images are used, the only limitation is the size of available RAM, since all of the operand images must be open in PixInsight for PixelMath to access them. Additional data structures and temporary images may be necessary during PixelMath execution, which are also allocated in RAM. Parenthesized expressions In PixInsight LE 1.0, there is no provision to build parenthesized expressions with PixelMath. If you need to operate with some images and your expression includes two or more parentheses, you may have to break it into appropriate subexpressions and use one instance of PixelMath to calculate each of them, then a final PixelMath to calculate the result. Parenthesized expressions are fully supported in PixInsight Standard. Sizes of operand images PixelMath can operate with images of any sizes. If an operand image and the target image have different dimensions, a temporary duplicate of the operand is generated, resampled to match the target, and the corresponding operation is performed. Then the temporary duplicate is destroyed and PixelMath continues with the next operand. Size-matching resampling operations are performed automatically on the fly. The bicubic interpolation algorithm is used. Operating between color and grayscale images With some restrictions, PixelMath can operate between grayscale and color images. If the target image is grayscale, then all of the operand images must also be grayscale. If the target is a color image and an operand is grayscale, the grayscale operand applies to each color channel of the target image. The accuracy of intermediate calculations The entire sequence of operations is accumulated as a temporary floating point matrix. During the whole calculation, the full IEEE 32-bit floating point range is used for each pixel. This gives a final accuracy better than, roughly, six or seven decimal digits, depending on the complexity of the whole process. Rescale or truncation to the normalized [0,1] range (as selected by the user) is performed at the very last calculation step to ensure minimal round-off error. The accuracy of rescale operations All rescale operations, including intermediate operations performed automatically, as well as the final rescaling to the normalized [0,1] range, when selected, are calculated with temporary variables in 64-bit IEEE floating point format. How bitwise logical operations are calculated PixInsight stores and manipulates pixel values as IEEE 32-bit floating point numbers. To apply bitwise logical operations (OR, AND, XOR), both target and operand pixel values are first transformed to unsigned 32-bit integers by multiplication with 4294967295 and rounding to the nearest integer. The multiplicative constant is equal to 232 – 1, the largest possible unsigned integer value. Note that this multiplication assumes pixel values in the normalized [0,1] range. Then the bitwise logical operation is performed and the result is back-converted to the normalized floating point range, transforming it to floating point format and dividing by 4294967295. When the target image is also used as an operand For example, this happens if the following PixelMath instance: <*target*> ADD Image01 ADD Image02 is applied to Image02. When this occurs, and PixelMath is being executed on the actual target image —not on a preview object—, a temporary duplicate of the target image is used to accumulate the result. The duplicate is generated at the beginning of the process, just before calculation starts. When the target image is not used as an operand, it works internally as a matrix where intermediate results are being accumulated. This is done to save memory. Using PixelMath with preview objects Instances of PixelMath can be applied to preview objects without any restrictions. When executed on a preview, PixelMath uses just those pixels falling into the preview rectangle, for all of the operand images, for the sake of execution speed. However, when an automatic resampling is needed to adapt mismatching operand dimensions, a temporary copy of the entire operand image is resampled, instead of the preview subimage, to ensure coherence between previewed and applied processes. The Pixel Math Window This is the standard interface to the PixelMath process described in the preceding section: Source Operands list box On this list box you can inspect all of the currently defined operands. The first list row corresponds to the target image.The rest of list rows correspond to PixelMath operands. The following columns are defined for this list: # Shows the operand number (zero for the target image). Op Shows the operator selected for each operand. Image Id The image identifier for each operand, if any has been selected. R/K, G, B These three columns are coefficients for the red/gray, green, and blue channels, respectively. Inv This column is checked on rows where inversion has been selected for the corresponding image. To select an operand or the target image, just click on the corresponding list row. Data corresponding to the item selected are loaded on, and can be edited with, the controls in the Current Operand Parameters section. Current Operand Parameters Controls in this area correspond to parameters of the currently selected operand (or target image) in the Source Operands list box. Operator combo box This control includes the whole set of available operators. This combo box is disabled if the target image is selected in the Source Operands list box. Operand combo box By clicking on this control you can select an image for the current operand, if any is currently open. You select an image by its image identifier, or the item labelled as "No view selected" if you don't want to have an image associated to the current operand. This combo box is disabled if the target image is selected in the Source Operands list box. When you select no image for an operand, all of the target pixels are operated with the channel coefficients of the operand. This works as if an image filled with a constant color, as defined by the channel coefficients, was associated with the operand. Channel Coefficient edit controls If an image has been selected for the current operand, these coefficients multiply the red (or gray), green, and blue channels, respectively, of the selected operand image. For the target image, the coefficients also multiply their respective channels. Finally, if no image has been selected for an operand, coefficients are directly operated, according to the selected operator, with the corresponding channels of the target image. Channel coefficients can range from -100 to +100. Default values are 1.0 for the three channels. For grayscale images, only the first coefficient is taken into account. Invert check box When the Invert check box is checked, the operand or target image is inverted prior calculation. This check box is disabled if there is no image selected for the current operand. This option is unselected by default. Reset Channel Coefficients / Inversion button Click this button to reset the three channel coefficients and the Invert check box to their default states. Default values are coefficients equal to 1.0 and no inversion. Move Operand buttons You can change the order of operands by clicking these buttons. Click the up-arrow button to move the current operand upwards. Click the down-arrow button to move the current operand downwards. As you click these buttons, you can see how the operands are reorganized on the Source Operands list box. Of course, the target image item (the first list row) cannot be moved. New button Click this button to add a new operand to the PixelMath instance. A new operand is created with default values that you can modify to match your needs. Delete button Click this button to remove the current operand from the PixelMath instance. Operand deletion cannot be undone. Clear button By clicking this button the entire operand set is deleted. This operation cannot be undone. Use this button to start definition of a new PixelMath instance from scratch. Result Parameters Controls in this section modify parameters that apply after the entire set of operands has been applied to the target image. Channel Coefficient edit controls These coefficients multiply their respective channels of the resulting target image. For grayscale images, only the first coefficient is considered. The default value is 1.0 for the three coefficients. Add Constant edit control This constant value is added to all pixels of the resulting image, just after multiplication by the corresponding channel coefficients. The default value is zero. Invert check box When this check box is checked, the resulting image is inverted after multiplication by the channel coefficients and addition of the constant value. This option is unselected by default. Rescale check box / edit When the Rescale check box is checked, resulting pixels are rescaled to the specified range of values. The rescaling range is defined as two boundaries such as the normalized [1,0] range cannot be exceeded. See the corresponding explanation on this document to learn how rescaling is applied. When the Rescale check box is unchecked, resulting pixels are truncated to the normalized [0,1] range and the two edit controls for range boundaries are disabled. The rescale option is enabled by default, and the rescaling range is the normalized [0,1] range. Destination Parameters This section determines how the resulting image is presented after PixelMath execution. Note that the following options are irrelevant when PixelMath is executed on a preview object. Replace Target radio button If this option is selected, the resulting image replaces the target image. Prior target contents can only be recovered by the Edit > Undo operation, provided that Undo is currently enabled for the target image window. Create New Image radio button The resulting image goes to a newly created window. The new window receives an automatically generated identifier consisting of the target image identifier plus a specific postfix. The postfix can be specified by global preferences (Edit > Preferences, Identifiers tab sheet). The default PixelMath postfix is "_pixelMath". For example, if PixelMath is applied to Image01, the resulting image window would be identified as "Image01_pixelMath". Successive PixelMath executions on the same target would generate unique image identifiers automatically: "Image01_pixelMath1", "Image01_pixelMath2", and so on.