Leptonica 1.54
Файл src/morph.c
#include <stdio.h>
#include <math.h>
#include "allheaders.h"

Функции

static PIXprocessMorphArgs1 (PIX *pixd, PIX *pixs, SEL *sel, PIX **ppixt)
static PIXprocessMorphArgs2 (PIX *pixd, PIX *pixs, SEL *sel)
PIXpixDilate (PIX *pixd, PIX *pixs, SEL *sel)
PIXpixErode (PIX *pixd, PIX *pixs, SEL *sel)
PIXpixHMT (PIX *pixd, PIX *pixs, SEL *sel)
PIXpixOpen (PIX *pixd, PIX *pixs, SEL *sel)
PIXpixClose (PIX *pixd, PIX *pixs, SEL *sel)
PIXpixCloseSafe (PIX *pixd, PIX *pixs, SEL *sel)
PIXpixOpenGeneralized (PIX *pixd, PIX *pixs, SEL *sel)
PIXpixCloseGeneralized (PIX *pixd, PIX *pixs, SEL *sel)
PIXpixDilateBrick (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixErodeBrick (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixOpenBrick (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixCloseBrick (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixCloseSafeBrick (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
l_int32 selectComposableSels (l_int32 size, l_int32 direction, SEL **psel1, SEL **psel2)
l_int32 selectComposableSizes (l_int32 size, l_int32 *pfactor1, l_int32 *pfactor2)
PIXpixDilateCompBrick (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixErodeCompBrick (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixOpenCompBrick (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixCloseCompBrick (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixCloseSafeCompBrick (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
void resetMorphBoundaryCondition (l_int32 bc)
l_uint32 getMorphBorderPixelColor (l_int32 type, l_int32 depth)

Переменные

LEPT_DLL l_int32 MORPH_BC = ASYMMETRIC_MORPH_BC
static const l_int32 ACCEPTABLE_COST = 5

Функции

l_uint32 getMorphBorderPixelColor ( l_int32  type,
l_int32  depth 
)

getMorphBorderPixelColor()

Input: type (L_MORPH_DILATE, L_MORPH_ERODE) depth (of pix) Return: color of border pixels for this operation

PIX* pixClose ( PIX pixd,
PIX pixs,
SEL sel 
)

pixClose()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) sel Return: pixd

Notes: (1) Generic morphological closing, using hits in the Sel. (2) This implementation is a strict dual of the opening if symmetric boundary conditions are used (see notes at top of this file). (3) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (4) For clarity, if the case is known, use these patterns: (a) pixd = pixClose(NULL, pixs, ...); (b) pixClose(pixs, pixs, ...); (c) pixClose(pixd, pixs, ...); (5) The size of the result is determined by pixs.

PIX* pixCloseBrick ( PIX pixd,
PIX pixs,
l_int32  hsize,
l_int32  vsize 
)

pixCloseBrick()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) hsize (width of brick Sel) vsize (height of brick Sel) Return: pixd, or null on error

Notes: (1) Sel is a brick with all elements being hits (2) The origin is at (x, y) = (hsize/2, vsize/2) (3) Do separably if both hsize and vsize are > 1. (4) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (5) For clarity, if the case is known, use these patterns: (a) pixd = pixCloseBrick(NULL, pixs, ...); (b) pixCloseBrick(pixs, pixs, ...); (c) pixCloseBrick(pixd, pixs, ...); (6) The size of the result is determined by pixs.

PIX* pixCloseCompBrick ( PIX pixd,
PIX pixs,
l_int32  hsize,
l_int32  vsize 
)

pixCloseCompBrick()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) hsize (width of brick Sel) vsize (height of brick Sel) Return: pixd, or null on error

Notes: (1) Sel is a brick with all elements being hits (2) The origin is at (x, y) = (hsize/2, vsize/2) (3) Do compositely for each dimension > 1. (4) Do separably if both hsize and vsize are > 1. (5) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (6) For clarity, if the case is known, use these patterns: (a) pixd = pixCloseCompBrick(NULL, pixs, ...); (b) pixCloseCompBrick(pixs, pixs, ...); (c) pixCloseCompBrick(pixd, pixs, ...); (7) The dimensions of the resulting image are determined by pixs. (8) CAUTION: both hsize and vsize are being decomposed. The decomposer chooses a product of sizes (call them 'terms') for each that is close to the input size, but not necessarily equal to it. It attempts to optimize: (a) for consistency with the input values: the product of terms is close to the input size (b) for efficiency of the operation: the sum of the terms is small; ideally about twice the square root of the input size. So, for example, if the input hsize = 37, which is a prime number, the decomposer will break this into two terms, 6 and 6, so that the net result is a dilation with hsize = 36.

PIX* pixCloseGeneralized ( PIX pixd,
PIX pixs,
SEL sel 
)

pixCloseGeneralized()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) sel Return: pixd

Notes: (1) Generalized morphological closing, using both hits and misses in the Sel. (2) This does a dilation using the hits, followed by a hit-miss transform. (3) This operation is a dual of the generalized opening. (4) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (5) For clarity, if the case is known, use these patterns: (a) pixd = pixCloseGeneralized(NULL, pixs, ...); (b) pixCloseGeneralized(pixs, pixs, ...); (c) pixCloseGeneralized(pixd, pixs, ...); (6) The size of the result is determined by pixs.

PIX* pixCloseSafe ( PIX pixd,
PIX pixs,
SEL sel 
)

pixCloseSafe()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) sel Return: pixd

Notes: (1) Generic morphological closing, using hits in the Sel. (2) If non-symmetric boundary conditions are used, this function adds a border of OFF pixels that is of sufficient size to avoid losing pixels from the dilation, and it removes the border after the operation is finished. It thus enforces a correct extensive result for closing. (3) If symmetric b.c. are used, it is not necessary to add and remove this border. (4) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (5) For clarity, if the case is known, use these patterns: (a) pixd = pixCloseSafe(NULL, pixs, ...); (b) pixCloseSafe(pixs, pixs, ...); (c) pixCloseSafe(pixd, pixs, ...); (6) The size of the result is determined by pixs.

PIX* pixCloseSafeBrick ( PIX pixd,
PIX pixs,
l_int32  hsize,
l_int32  vsize 
)

pixCloseSafeBrick()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) hsize (width of brick Sel) vsize (height of brick Sel) Return: pixd, or null on error

Notes: (1) Sel is a brick with all elements being hits (2) The origin is at (x, y) = (hsize/2, vsize/2) (3) Do separably if both hsize and vsize are > 1. (4) Safe closing adds a border of 0 pixels, of sufficient size so that all pixels in input image are processed within 32-bit words in the expanded image. As a result, there is no special processing for pixels near the boundary, and there are no boundary effects. The border is removed at the end. (5) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (6) For clarity, if the case is known, use these patterns: (a) pixd = pixCloseBrick(NULL, pixs, ...); (b) pixCloseBrick(pixs, pixs, ...); (c) pixCloseBrick(pixd, pixs, ...); (7) The size of the result is determined by pixs.

PIX* pixCloseSafeCompBrick ( PIX pixd,
PIX pixs,
l_int32  hsize,
l_int32  vsize 
)

pixCloseSafeCompBrick()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) hsize (width of brick Sel) vsize (height of brick Sel) Return: pixd, or null on error

Notes: (1) Sel is a brick with all elements being hits (2) The origin is at (x, y) = (hsize/2, vsize/2) (3) Do compositely for each dimension > 1. (4) Do separably if both hsize and vsize are > 1. (5) Safe closing adds a border of 0 pixels, of sufficient size so that all pixels in input image are processed within 32-bit words in the expanded image. As a result, there is no special processing for pixels near the boundary, and there are no boundary effects. The border is removed at the end. (6) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (7) For clarity, if the case is known, use these patterns: (a) pixd = pixCloseSafeCompBrick(NULL, pixs, ...); (b) pixCloseSafeCompBrick(pixs, pixs, ...); (c) pixCloseSafeCompBrick(pixd, pixs, ...); (8) The dimensions of the resulting image are determined by pixs. (9) CAUTION: both hsize and vsize are being decomposed. The decomposer chooses a product of sizes (call them 'terms') for each that is close to the input size, but not necessarily equal to it. It attempts to optimize: (a) for consistency with the input values: the product of terms is close to the input size (b) for efficiency of the operation: the sum of the terms is small; ideally about twice the square root of the input size. So, for example, if the input hsize = 37, which is a prime number, the decomposer will break this into two terms, 6 and 6, so that the net result is a dilation with hsize = 36.

PIX* pixDilate ( PIX pixd,
PIX pixs,
SEL sel 
)

pixDilate()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) sel Return: pixd

Notes: (1) This dilates src using hits in Sel. (2) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (3) For clarity, if the case is known, use these patterns: (a) pixd = pixDilate(NULL, pixs, ...); (b) pixDilate(pixs, pixs, ...); (c) pixDilate(pixd, pixs, ...); (4) The size of the result is determined by pixs.

PIX* pixDilateBrick ( PIX pixd,
PIX pixs,
l_int32  hsize,
l_int32  vsize 
)

pixDilateBrick()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) hsize (width of brick Sel) vsize (height of brick Sel) Return: pixd

Notes: (1) Sel is a brick with all elements being hits (2) The origin is at (x, y) = (hsize/2, vsize/2) (3) Do separably if both hsize and vsize are > 1. (4) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (5) For clarity, if the case is known, use these patterns: (a) pixd = pixDilateBrick(NULL, pixs, ...); (b) pixDilateBrick(pixs, pixs, ...); (c) pixDilateBrick(pixd, pixs, ...); (6) The size of the result is determined by pixs.

PIX* pixDilateCompBrick ( PIX pixd,
PIX pixs,
l_int32  hsize,
l_int32  vsize 
)

pixDilateCompBrick()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) hsize (width of brick Sel) vsize (height of brick Sel) Return: pixd, or null on error

Notes: (1) Sel is a brick with all elements being hits (2) The origin is at (x, y) = (hsize/2, vsize/2) (3) Do compositely for each dimension > 1. (4) Do separably if both hsize and vsize are > 1. (5) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (6) For clarity, if the case is known, use these patterns: (a) pixd = pixDilateCompBrick(NULL, pixs, ...); (b) pixDilateCompBrick(pixs, pixs, ...); (c) pixDilateCompBrick(pixd, pixs, ...); (7) The dimensions of the resulting image are determined by pixs. (8) CAUTION: both hsize and vsize are being decomposed. The decomposer chooses a product of sizes (call them 'terms') for each that is close to the input size, but not necessarily equal to it. It attempts to optimize: (a) for consistency with the input values: the product of terms is close to the input size (b) for efficiency of the operation: the sum of the terms is small; ideally about twice the square root of the input size. So, for example, if the input hsize = 37, which is a prime number, the decomposer will break this into two terms, 6 and 6, so that the net result is a dilation with hsize = 36.

PIX* pixErode ( PIX pixd,
PIX pixs,
SEL sel 
)

pixErode()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) sel Return: pixd

Notes: (1) This erodes src using hits in Sel. (2) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (3) For clarity, if the case is known, use these patterns: (a) pixd = pixErode(NULL, pixs, ...); (b) pixErode(pixs, pixs, ...); (c) pixErode(pixd, pixs, ...); (4) The size of the result is determined by pixs.

PIX* pixErodeBrick ( PIX pixd,
PIX pixs,
l_int32  hsize,
l_int32  vsize 
)

pixErodeBrick()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) hsize (width of brick Sel) vsize (height of brick Sel) Return: pixd

Notes: (1) Sel is a brick with all elements being hits (2) The origin is at (x, y) = (hsize/2, vsize/2) (3) Do separably if both hsize and vsize are > 1. (4) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (5) For clarity, if the case is known, use these patterns: (a) pixd = pixErodeBrick(NULL, pixs, ...); (b) pixErodeBrick(pixs, pixs, ...); (c) pixErodeBrick(pixd, pixs, ...); (6) The size of the result is determined by pixs.

PIX* pixErodeCompBrick ( PIX pixd,
PIX pixs,
l_int32  hsize,
l_int32  vsize 
)

pixErodeCompBrick()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) hsize (width of brick Sel) vsize (height of brick Sel) Return: pixd, or null on error

Notes: (1) Sel is a brick with all elements being hits (2) The origin is at (x, y) = (hsize/2, vsize/2) (3) Do compositely for each dimension > 1. (4) Do separably if both hsize and vsize are > 1. (5) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (6) For clarity, if the case is known, use these patterns: (a) pixd = pixErodeCompBrick(NULL, pixs, ...); (b) pixErodeCompBrick(pixs, pixs, ...); (c) pixErodeCompBrick(pixd, pixs, ...); (7) The dimensions of the resulting image are determined by pixs. (8) CAUTION: both hsize and vsize are being decomposed. The decomposer chooses a product of sizes (call them 'terms') for each that is close to the input size, but not necessarily equal to it. It attempts to optimize: (a) for consistency with the input values: the product of terms is close to the input size (b) for efficiency of the operation: the sum of the terms is small; ideally about twice the square root of the input size. So, for example, if the input hsize = 37, which is a prime number, the decomposer will break this into two terms, 6 and 6, so that the net result is a dilation with hsize = 36.

PIX* pixHMT ( PIX pixd,
PIX pixs,
SEL sel 
)

pixHMT()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) sel Return: pixd

Notes: (1) The hit-miss transform erodes the src, using both hits and misses in the Sel. It ANDs the shifted src for hits and ANDs the inverted shifted src for misses. (2) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (3) For clarity, if the case is known, use these patterns: (a) pixd = pixHMT(NULL, pixs, ...); (b) pixHMT(pixs, pixs, ...); (c) pixHMT(pixd, pixs, ...); (4) The size of the result is determined by pixs.

PIX* pixOpen ( PIX pixd,
PIX pixs,
SEL sel 
)

pixOpen()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) sel Return: pixd

Notes: (1) Generic morphological opening, using hits in the Sel. (2) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (3) For clarity, if the case is known, use these patterns: (a) pixd = pixOpen(NULL, pixs, ...); (b) pixOpen(pixs, pixs, ...); (c) pixOpen(pixd, pixs, ...); (4) The size of the result is determined by pixs.

PIX* pixOpenBrick ( PIX pixd,
PIX pixs,
l_int32  hsize,
l_int32  vsize 
)

pixOpenBrick()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) hsize (width of brick Sel) vsize (height of brick Sel) Return: pixd, or null on error

Notes: (1) Sel is a brick with all elements being hits (2) The origin is at (x, y) = (hsize/2, vsize/2) (3) Do separably if both hsize and vsize are > 1. (4) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (5) For clarity, if the case is known, use these patterns: (a) pixd = pixOpenBrick(NULL, pixs, ...); (b) pixOpenBrick(pixs, pixs, ...); (c) pixOpenBrick(pixd, pixs, ...); (6) The size of the result is determined by pixs.

PIX* pixOpenCompBrick ( PIX pixd,
PIX pixs,
l_int32  hsize,
l_int32  vsize 
)

pixOpenCompBrick()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) hsize (width of brick Sel) vsize (height of brick Sel) Return: pixd, or null on error

Notes: (1) Sel is a brick with all elements being hits (2) The origin is at (x, y) = (hsize/2, vsize/2) (3) Do compositely for each dimension > 1. (4) Do separably if both hsize and vsize are > 1. (5) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (6) For clarity, if the case is known, use these patterns: (a) pixd = pixOpenCompBrick(NULL, pixs, ...); (b) pixOpenCompBrick(pixs, pixs, ...); (c) pixOpenCompBrick(pixd, pixs, ...); (7) The dimensions of the resulting image are determined by pixs. (8) CAUTION: both hsize and vsize are being decomposed. The decomposer chooses a product of sizes (call them 'terms') for each that is close to the input size, but not necessarily equal to it. It attempts to optimize: (a) for consistency with the input values: the product of terms is close to the input size (b) for efficiency of the operation: the sum of the terms is small; ideally about twice the square root of the input size. So, for example, if the input hsize = 37, which is a prime number, the decomposer will break this into two terms, 6 and 6, so that the net result is a dilation with hsize = 36.

PIX* pixOpenGeneralized ( PIX pixd,
PIX pixs,
SEL sel 
)

pixOpenGeneralized()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) sel Return: pixd

Notes: (1) Generalized morphological opening, using both hits and misses in the Sel. (2) This does a hit-miss transform, followed by a dilation using the hits. (3) There are three cases: (a) pixd == null (result into new pixd) (b) pixd == pixs (in-place; writes result back to pixs) (c) pixd != pixs (puts result into existing pixd) (4) For clarity, if the case is known, use these patterns: (a) pixd = pixOpenGeneralized(NULL, pixs, ...); (b) pixOpenGeneralized(pixs, pixs, ...); (c) pixOpenGeneralized(pixd, pixs, ...); (5) The size of the result is determined by pixs.

static PIX * processMorphArgs1 ( PIX pixd,
PIX pixs,
SEL sel,
PIX **  ppixt 
) [static]

processMorphArgs1()

Input: pixd (<optional>; this can be null, equal to pixs, or different from pixs) pixs (1 bpp) sel &pixt (<returned>) Return: pixd, or null on error.

Notes: (1) This is used for generic erosion, dilation and HMT.

static PIX * processMorphArgs2 ( PIX pixd,
PIX pixs,
SEL sel 
) [static]

processMorphArgs2()

This is used for generic openings and closings.

void resetMorphBoundaryCondition ( l_int32  bc)

resetMorphBoundaryCondition()

Input: bc (SYMMETRIC_MORPH_BC, ASYMMETRIC_MORPH_BC) Return: void

l_int32 selectComposableSels ( l_int32  size,
l_int32  direction,
SEL **  psel1,
SEL **  psel2 
)
l_int32 selectComposableSizes ( l_int32  size,
l_int32 pfactor1,
l_int32 pfactor2 
)

selectComposableSizes()

Input: size (of sel to be decomposed) &factor1 (<return> larger factor) &factor2 (<return> smaller factor) Return: 0 if OK, 1 on error

Notes: (1) This works for Sel sizes up to 62500, which seems sufficient. (2) The composable sel size is typically within +- 1 of the requested size. Up to size = 300, the maximum difference is +- 2. (3) We choose an overall cost function where the penalty for the size difference between input and actual is 4 times the penalty for additional rasterops. (4) Returned values: factor1 >= factor2 If size > 1, then factor1 > 1.


Переменные

const l_int32 ACCEPTABLE_COST = 5 [static]
LEPT_DLL l_int32 MORPH_BC = ASYMMETRIC_MORPH_BC