Image processing Isis software documentation

Image processing

This library contains several image processing utilities, including transfers, clearing, compositing, gain and bias, filters, affine transformations, etc. Images are handled using the image buffer protocol, which you should read about before using these procedures.

In all of the following functions, two-dimensional sizes, offsets, locations, etc., are passed to functions in lists. For example, a two-dimensional size is specified as [xsize ysize].


Buffer manipulation

If you haven't already done so, please read the section about intersecting image buffers using the image buffer protocol now. Since most of the following image processing primitives will only work on buffers that are the same size, you may need to call intersect-images in order to isolate identically-sized sub-images of the buffers involved in the operation you want to perform.


Clearing

(image-fill-constant val outbuf) This routine fills an image buffer with a specified numerical value. The value is converted to the sample type of the image buffer. The value must be within the range of possible values for that sample type--it will not be clamped automatically. The return value is the output image buffer.


Simple transfers

(image-transfer inbuf outbuf) (image-transfer-range low high inbuf outbuf) (image-transfer-range-rgb rlow rhigh glow ghigh blow bhigh inbuf outbuf) (image-copy inbuf) image-transfer transfers one image into another. image-transfer-range transfers only a certain range of pixel values (between low and high inclusive) from one image to another. image-transfer-range-rgb does the same thing with the additional constraints that the images must have three channels and corresponding pixels in each of the three channels must all lie within their respective ranges in order to be transferred. The input and output images must be the same type and size (use intersect-images if necessary), and the return value is the output image buffer.

image-copy creates an identical copy of an image by creating a new buffer and transfering the old image into it. The return value is the new image buffer.


Sample type conversion

(image-convert inbuf outbuf) This routine transfers one image into another, converting the sample type of the input image to that of the output image in the process. The images must be the same size. No range clamping is performed, so overflow errors are possible when converting from a larger to a smaller sample type. The return value is the output image buffer.


Filters

(image-gainbias gain bias inbuf outbuf) (image-filter-1d taps centertap mirror-flag inbuf outbuf) (image-filter-2d taps centertap mirror-flag inbuf outbuf) (image-remap-intensity remapaddr inbuf outbuf) # see documentation image-gainbias gains and biases each pixel in the input image and places the result in the output image. The images must be the same size, but they do not have to have the same sample type (an error message will be printed if a particular conversion is not supported). Appropriate range clamping is performed when using byte or short-sampled images.

image-filter-1d convolves each scanline in the input image with a one-dimensional filter and places the result in the output image which must be the same size. taps should be a list of real numbers of arbitrary length specifying the filter taps. centertap should be an integer index indicating the center of the tap list. mirror-flag should be True if the image should be "mirrored" to provide better filter output at the edges, and False if not (slightly faster).

image-filter-2d performs a two-dimensional convolution over the entire image. taps should be a list of lists of real numbers indicating the taps for each "line" of the filter, and centertap should be a list of two integers [xcenter ycenter] indicating the center of the tap array. The rest of the arguments are the same as before.

image-remap-intensity works only on byte-sampled images. It remaps the pixel values in the input image and places the result in the output image. remapaddr is the address of a 256-byte array specifying the correspondance between new and old pixel values. For example, to remap all pixels which have the value 3 to have the new value 159, remapaddr should have the value 159 at index 3. You can create this array using the utilities in the memory manipulation library.

The return value in all cases is the output image buffer.


Image arithmetic

(image-add buf1 buf2 outbuf) (image-subtract buf1 buf2 outbuf) (image-diff buf1 buf2 outbuf) # absolute value difference (image-multiply buf1 buf2 outbuf) (image-divide buf1 buf2 outbuf) (image-maximum buf1 buf2 outbuf) (image-minimum buf1 buf2 outbuf) These functions perform pixelwise arithmetic operations on images. In all cases, the buffers must be the same size. Usually, the sample type of all buffers involved must also be the same. An error message is printed if the combination of image types presented to an operation is unsupported. Appropriate range clamping is performed when operating on byte-sampled images. The return value in all cases is the output image buffer.


Bounding boxes

(image-bounding-box low high imagebuf) (image-bounding-box-rgb rlow rhigh glow ghigh blow bhigh imagebuf) (image-fuzzy-bounding-box thresh pixcount imagebuf) These functions find bounding boxes around features in an image. image-bounding-box returns the smallest rectangle that bounds all the pixels in the image of value between low and high inclusive. image-bounding-box-rgb does the same thing for pixels in a 3-channel image buffer that satisfy all three of the red, green and blue ranges specified. The rectangle is returned as a list of 4 integers [x1 y1 x2 y2]. If no such box can be found, Null is returned.

image-fuzzy-bounding-box is a fuzzy bounding box algorithm that is helpful in eliminating the effects of salt and pepper noise when looking for bounding boxes. The function returns the smallest rectangle that bounds all areas of the image where the sum of pixcount adjacent horizontal pixels is greater than or equal to thresh. The return value is the same as before.


Flood Fill

(image-flood-fill inbuf seed-point outbuf) image-flood-fill extracts a selected object in an image via flood fill. This function will only work on 64-bit architectures.

inbuf is an image buffer containing an alpha plane which defines multiple foreground objects against a single background. The background pixels are marked with a '0' while the pixels of the foreground objects are those with non-zero values. Data type is either c-short or c-byte.

seed-point is a pixel position in the alpha plane. Starting from the seed point, all foreground pixels which have an unbroken connection to the seed point are selected via flood fill.

On completion outbuf contains an alpha plane with the single selected foreground object marked with 1's and the remainder marked with 0's. Specification of an outbuf is optional. If no preallocated buffer is supplied, one is created and returned. Data type is c-byte.

This function is principally characterized by its speed. The flood fill routine has been hand optimized for use on machines with a 64-bit wide machine word. The throughput is 56 pixel positions per 8 machine clock cycles.

There is no differentiation between the foreground objects based on the values in the alpha plane. Any non-zero value denotes a foreground pixel and distinct foreground objects must be separated by background pixels.


Compositing

(image-composite inbuf abuf outbuf) (image-composite-constalpha alphaval inbuf outbuf) (image-composite-remapalpha remapaddr inbuf abuf outbuf) These functions perform image compositing, i.e. the blending of a foreground image into a background image utilizing a one-channel byte-sampled transparency (or "alpha") image of the same size to determine the opacity of each pixel in the foreground image. In this alpha channel, a value of 0 means the pixel is fully transparent, and 255 means the pixel is completely opaque, and values in between indicate varying levels of opacity. All images involved must be the same size and byte-sampled.

image-composite expects the input foreground image, alpha image, and output background image as arguments and performs the standard composition as described above.

image-composite-constalpha composites an input image into an output image using a constant "alpha" value which must be an integer between 0 and 255.

image-composite-remapalpha works the same as image-composite except that each value in the alpha image is first "remapped" to a new value. remapaddr should be the address of a 256-byte array specifying the correspondance between new and old alpha values. One way to create this array is to use the utilities in the memory manipulation library.


Scaling

(image-simple-scale inbuf outbuf) # input scaled to exact size of outbuf (image-aspect-scale inbuf outbuf) # input scaled to fit inside outbuf (image-scale inbuf outbuf xremapaddr yremapaddr) (image-scale-range low high inbuf outbuf xremapaddr yremapaddr) (image-scale-composite inbuf abuf outbuf xremapaddr yremapaddr) (image-scale-composite-constalpha alphaval inbuf outbuf xremapaddr yremapaddr) (image-scale-composite-remapalpha remapaddr inbuf abuf outbuf xremapaddr yremapaddr) (new-scale-remap scale linelen) # create a remap array for an exact scale These functions perform image scaling. The simplest version is image-simple-scale which scales the input image to the exact size of the output image. image-aspect-scale scales the input image to fit inside the output image, maintaining the aspect ratio of the input image.

The other five scaling functions work the same way as image-transfer, image-transfer-range, image-composite, image-composite-constalpha, and image-composite-remapalpha except that they scale the image as it is being processed. Two arguments, xremapaddr and yremapaddr, are expected in addition to the normal arguments for these operations. These arguments are addresses of arrays of integers indicating how to remap the image in the horizontal and vertical directions. Each value in the array indicates the location in the input image from which to obtain the value for each pixel in the output image. For example, a value of 34 at position 12 means that the 34th pixel in the input image will be transferred to the 12th position in the output image. Therefore, these arrays must be at least the length of the corresponding dimension of the output image.

new-scale-remap can be used to create an array of length linelen appropriate for remapping pixels at a particular exact scale factor. The return value of this function is the address of the array which should be freed when no longer needed. To create remap arrays for more complex transformations, use the utilities in the memory manipulation library.


Affine transformations

(affine-rotate degrees) (affine-scale scale) (affine-scale [xscale yscale]) (affine-translate [xpos ypos]) (affine-shear [xshear yshear]) (affine-combine params1 params2 params3 ...) # composes operations in order (image-affine-trans affine-params reverse-flag inbuf outbuf) (affine-trans-point affine-params point) These functions perform affine transformations on images. Before processing the image, the affine parameters for a particular transformation should be calculated. The first 5 functions listed above return affine parameters, in the form of a list of 6 real numbers, to accomplish a particular operation. To combine several operations in order, call affine-combine with the corresponding affine parameter lists as arguments.

image-affine-trans applies the affine transformation to an image. affine-params should be the list of 6 real number affine parameters obtained from using the routines described above. reverse-flag should be a boolean indicating whether the remapping should be performed in a forward (False) or reverse (True) fashion. In almost all cases, reverse-flag should be True. The final two arguments are the input and output image buffers which must be of the same type. The return value is the output image buffer. Pixels laying outside the boundaries of the input or output image buffers are not transferred.

affine-trans-point transforms a single point [xpos ypos] using the specified affine parameters.


Motion Estimation

(image-optical-flow image-1 image-2 warp-Y warp-X) image-optical-flow computes the pixelwise 2D field which describes the warp from one image to an other. The pair image-1 and image-2 are assumed to be temporally adjacent images taken a video sequence. On completion, warp-Y contains the pixelwise vertical displacement and warp-X contains the horizontal displacement.

All four parameters must be single channel image buffers of identical size. Both image buffers should be c-byte datatype. The displacement buffers should be type c-float.

This function uses gradient constraint to compute the displacement due to motion between the two images. Gradient constraint is a variant of optical flow which has been optimized for recovering the motion in natural scenes. This particular realization, based on the PhD theses of Dennis Martinez and Ed Krause, employs a series of hierarchical refinements to the vector field ... resulting in very robust estimates but a run time that is somewhat slow.


Image warping

(image-warp-map affine-params srcsize warpbuf) (image-warp interp-flag inbuf outbuf warpbuf) image-warp performs a pixel-by-pixel remapping (or "warp") of an input image to an output image. It requires a integer-sampled "remapping image" (warpbuf) which is the same size as the output image. This remapping image must have 2 channels, one for X and one for Y. For each pixel in the output image, the corresponding point in the remapping image is consulted to determine which pixel from the input image will be copied there.

image-warp-map generates a suitable remapping image for a source image of size srcsize from a list of 6 affine parameters. warpbuf must be a two-channel integer-sampled image. Use the affine- functions described above to calculate affine parameters.

It is possible to have a fractional mapping, e.g. Dest[10 10] = Src[9.25 10.25]. In order to provide for fast, efficient interpolation methods, fixed point mathematics is used in the remapping. image-warp-map generates the correct fixed-point integer warp map for a given set of affine paramters. If another routine for generating the warp map will be used, it must follow the same fixed-point strategy: The last 8 bits are for the mantissa (i.e. fractional part) and the upper 24 bits are for the whole number. In order to convert a floating point number, say 9.25, to a fixed point integer, just multiply the whole number by 256, and typecast to an integer. So 9.25 * 256 = 2368.

If interp-flag is True, then tri-linear interpolation on the source data is performed. Otherwise, the fractional index is truncated. Tri-linear interpolation is slower than truncation but looks better.

No boundary checking is done on the position values in the remapping image. If you use your own warp-map generator, be sure to specify mappings that are always within the bounds of the source image. image-warp-map satisfies this requirement.

Example

(set input-image (retrieve-url-image "file:/usr/local/isis/media/nana.jpg")) (set inputsize (input-image buf-size)) (set output-image (new-image c-byte 3 [300 300])) (set remap-image (new-image c-int 2 [300 300])) (set params (affine-combine (affine-translate (* [-0.5 -0.5] inputsize)) (affine-scale 0.5) (affine-rotate 45) (affine-translate [150 150]))) (image-warp-map params inputsize remap-image) (image-warp False input-image output-image remap-image) (set inwin (xwin-create Null "Original" Null inputsize)) (xwin-display-image inwin input-image) (set outwin (xwin-create Null "Warped" Null [300 300])) (xwin-display-image outwin output-image)


Requirements:
Scripts: (load "image-processing.isis")
Libraries: -lisis_improc
Headers: isis_improc.h
Binders: bind_improc_library(script);


Thanks to Shawn Becker, Chris Dodge, and Jon Dakss for their contributions to this library.