## morphology

morphology — morphological operators, rank filters and related image analysis

## Stability Level

Stable, unless otherwise indicated

## Synopsis

    #include <vips/vips.h>

    int                 im_dilate                           (VipsImage *in,
                                                             VipsImage *out,
                                                             INTMASK *mask);
    int                 im_erode                            (VipsImage *in,
                                                             VipsImage *out,
                                                             INTMASK *mask);
    int                 im_rank                             (VipsImage *in,
                                                             VipsImage *out,
                                                             int width,
                                                             int height,
                                                             int index);
    int                 im_rank_image                       (VipsImage **in,
                                                             VipsImage *out,
                                                             int n,
                                                             int index);
    int                 im_maxvalue                         (VipsImage **in,
                                                             VipsImage *out,
                                                             int n);
    int                 im_cntlines                         (VipsImage *im,
                                                             double *nolines,
                                                             int flag);
    int                 im_zerox                            (VipsImage *in,
                                                             VipsImage *out,
                                                             int sign);
    int                 im_profile                          (VipsImage *in,
                                                             VipsImage *out,
                                                             int dir);
    int                 im_label_regions                    (VipsImage *test,
                                                             VipsImage *mask,
                                                             int *segments);

## Description

The morphological functions search images for particular patterns of pixels, specified with the mask argument, either adding or removing pixels when they find a match. They are useful for cleaning up images --- for example, you might threshold an image, and then use one of the morphological functions to remove all single isolated pixels from the result.

If you combine the morphological operators with the mask rotators `im_rotate_imask45()`, for example) and apply them repeatedly, you can achieve very complicated effects: you can thin, prune, fill, open edges, close gaps, and many others. For example, see `Fundamentals of Digital Image Processing' by A. Jain, pp 384-388, Prentice-Hall, 1989 for more ideas.

Beware that VIPS reverses the usual image processing convention, by assuming white objects (non-zero pixels) on a black background (zero pixels).

The mask you give to the morphological functions should contain only the values 0 (for background), 128 (for don't care) and 255 (for object). The mask must have odd length sides --- the origin of the mask is taken to be the centre value. For example, the mask:

3 3 128 255 128 255 0 255 128 255 128

applied to an image with `im_erode()`, will find all black pixels 4-way connected with white pixels. Essentially, `im_dilate()` sets pixels in the output if any part of the mask matches, whereas `im_erode()` sets pixels only if all of the mask matches.

See `im_andimage()`, `im_orimage()` and `im_eorimage()` for analogues of the usual set difference and set union operations.

## Details

### im_dilate ()

    int                 im_dilate                           (VipsImage *in,
                                                             VipsImage *out,
                                                             INTMASK *mask);

`im_dilate()` performs a morphological dilate operation on `in` using `mask` as a structuring element. The output pixel is set if any part of the mask matches, that is, the result is the logical OR of the selected input pixels.

The image should have 0 (black) for no object and 255 (non-zero) for an object. Note that this is the reverse of the usual convention for these operations, but more convenient when combined with the boolean operators `im_andimage()` and friends. The output image is the same size as the input image: edge pxels are made by expanding the input image as necessary in the manner of `im_conv()`.

Mask coefficients can be either 0 (for object) or 255 (for background) or 128 (for do not care). The origin of the mask is at location (m.xsize / 2, m.ysize / 2), integer division. All algorithms have been based on the book "Fundamentals of Digital Image Processing" by A. Jain, pp 384-388, Prentice-Hall, 1989.

See the boolean operations `im_andimage()`, `im_orimage()` and `im_eorimage()` for analogues of the usual set difference and set union operations.

Operations are performed using the processor's vector unit, if possible. Disable this with --vips-novector or IM_NOVECTOR.

See also: `im_erode()`.

`in` : | input image
`out` : | output image
`mask` : | mask
Returns : | 0 on success, -1 on error

### im_erode ()

    int                 im_erode                            (VipsImage *in,
                                                             VipsImage *out,
                                                             INTMASK *mask);

`im_erode()` performs a morphological erode operation on `in` using `mask` as a structuring element. The whole mask must match for the output pixel to be set, that is, the result is the logical AND of the selected input pixels.

The image should have 0 (black) for no object and 255 (non-zero) for an object. Note that this is the reverse of the usual convention for these operations, but more convenient when combined with the boolean operators `im_andimage()` and friends. The output image is the same size as the input image: edge pxels are made by expanding the input image as necessary in the manner of `im_conv()`.

Mask coefficients can be either 0 (for object) or 255 (for background) or 128 (for do not care). The origin of the mask is at location (m.xsize / 2, m.ysize / 2), integer division. All algorithms have been based on the book "Fundamentals of Digital Image Processing" by A. Jain, pp 384-388, Prentice-Hall, 1989.

See the boolean operations `im_andimage()`, `im_orimage()` and `im_eorimage()` for analogues of the usual set difference and set union operations.

Operations are performed using the processor's vector unit, if possible. Disable this with --vips-novector or IM_NOVECTOR.

See also: `im_dilate()`.

`in` : | input image
`out` : | output image
`mask` : | mask
Returns : | 0 on success, -1 on error

### im_rank ()

    int                 im_rank                             (VipsImage *in,
                                                             VipsImage *out,
                                                             int width,
                                                             int height,
                                                             int index);

`im_rank()` does rank filtering on an image. A window of size `width` by `height` is passed over the image. At each position, the pixels inside the window are sorted into ascending order and the pixel at position `index` is output. `index` numbers from 0.

It works for any non-complex image type, with any number of bands. The input is expanded by copying edge pixels before performing the operation so that the output image has the same size as the input. Edge pixels in the output image are therefore only approximate.

For a median filter with mask size m (3 for 3x3, 5 for 5x5, etc.) use

im_rank( in, out, m, m, m * m / 2 );

The special cases n == 0 and n == m * m - 1 are useful dilate and expand operators.

See also: `im_conv()`, `im_fastcor()`.

`in` : | input image
`out` : | output image
`width` : | window width
`height` : | window height
`index` : | select pixel
Returns : | 0 on success, -1 on error

### im_rank_image ()

    int                 im_rank_image                       (VipsImage **in,
                                                             VipsImage *out,
                                                             int n,
                                                             int index);

`im_rank_image()` sorts the images `in` pixel-wise, then outputs an image in which each pixel is selected from the sorted list by the `index` parameter. For example, if `index` is zero, then each output pixel will be the minimum of all the corresponding input pixels.

It works for any uncoded, non-complex image type. Images are cast up to the smallest common-format.

Any image can have either 1 band or n bands, where n is the same for all the non-1-band images. Single band images are then effectively copied to make n-band images.

See also: `im_rank()`, `im_maxvalue()`.

`in` : | input image array
`out` : | output image
`n` : | number of input images
`index` : | select pixel
Returns : | 0 on success, -1 on error

### im_maxvalue ()

    int                 im_maxvalue                         (VipsImage **in,
                                                             VipsImage *out,
                                                             int n);

`im_maxvalue()` is a convenience function over `im_rank_image()`. It sorts the input images pixel-wise, then outputs an image in which each pixel is the maximum of all the corresponding input images. It works for any uncoded, non-complex image type. Images are cast up to the smallest common-format.

Any image can have either 1 band or n bands, where n is the same for all the non-1-band images. Single band images are then effectively copied to make n-band images.

See also: `im_rank_image()`.

`in` : | input image array
`out` : | output image
`n` : | number of input images
Returns : | 0 on success, -1 on error

### im_cntlines ()

    int                 im_cntlines                         (VipsImage *im,
                                                             double *nolines,
                                                             int flag);

Function which calculates the number of transitions between black and white for the horizontal or the vertical direction of an image. black<128 , white>=128 The function calculates the number of transitions for all Xsize or Ysize and returns the mean of the result Input should be one band, 8-bit.

See also: `im_erode()`, `im_zerox()`, `im_conv()`.

`im` : | input IMAGE
`nolines` : | output average number of lines
`flag` : | 0 horizontal, 1 vertical
Returns : | 0 on success, -1 on error.

### im_zerox ()

    int                 im_zerox                            (VipsImage *in,
                                                             VipsImage *out,
                                                             int sign);

`im_zerox()` detects the positive or negative zero crossings `in`, depending on `sign`. If `sign` is -1, negative zero crossings are returned, if `sign` is 1, positive zero crossings are returned.

The output image is byte with zero crossing set to 255 and all other values set to zero. Input can have any number of channels, and be any non-complex type.

See also: `im_conv()`, im_rot90.

`in` : | input image
`out` : | output image
`sign` : | detect positive or negative zero crossings
Returns : | 0 on success, -1 on error

### im_profile ()

    int                 im_profile                          (VipsImage *in,
                                                             VipsImage *out,
                                                             int dir);

`im_profile()` searches inward from the edge of `in` and finds the first non-zero pixel. It outputs an image containing a list of the offsets for each row or column.

If `dir` == 0, then `im_profile()` searches down from the top edge, writing an image as wide as the input image, but only 1 pixel high, containing the number of pixels down to the first non-zero pixel for each column of input pixels.

If `dir` == 1, then `im_profile()` searches across from the left edge, writing an image as high as the input image, but only 1 pixel wide, containing the number of pixels across to the first non-zero pixel for each row of input pixels.

See also: `im_cntlines()`.

`in` : | input image
`out` : | output image
`dir` : | search direction
Returns : | 0 on success, -1 on error

### im_label_regions ()

    int                 im_label_regions                    (VipsImage *test,
                                                             VipsImage *mask,
                                                             int *segments);

`im_label_regions()` repeatedly scans `test` for regions of 4-connected pixels with the same pixel value. Every time a region is discovered, those pixels are marked in `mask` with a unique serial number. Once all pixels have been labelled, the operation returns, setting `segments` to the number of discrete regions which were detected.

`mask` is always a 1-band `IM_BANDFMT_UINT` image of the same dimensions as `test`.

This operation is useful for, for example, blob counting. You can use the morphological operators to detect and isolate a series of objects, then use `im_label_regions()` to number them all.

Use `im_histindexed()` to (for example) find blob coordinates.

See also: `im_histindexed()`

`test` : | image to test
`mask` : | write labelled regions here
`segments` : | return number of regions here
Returns : | 0 on success, -1 on error.

## See Also

boolean