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

Макросы

#define DEBUG_SEL_LOOKUP   0

Функции

PIXpixDilateBrickDwa (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixErodeBrickDwa (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixOpenBrickDwa (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixCloseBrickDwa (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixDilateCompBrickDwa (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixErodeCompBrickDwa (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixOpenCompBrickDwa (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixCloseCompBrickDwa (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixDilateCompBrickExtendDwa (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixErodeCompBrickExtendDwa (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixOpenCompBrickExtendDwa (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
PIXpixCloseCompBrickExtendDwa (PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
l_int32 getExtendedCompositeParameters (l_int32 size, l_int32 *pn, l_int32 *pextra, l_int32 *pactualsize)

Макросы

#define DEBUG_SEL_LOOKUP   0

Функции

l_int32 getExtendedCompositeParameters ( l_int32  size,
l_int32 pn,
l_int32 pextra,
l_int32 pactualsize 
)

getExtendedCompositeParameters()

Input: size (of linear Sel) &pn (<return> number of 63 wide convolutions) &pextra (<return> size of extra Sel) &actualsize (<optional return>=""> actual size used in operation) Return: 0 if OK, 1 on error

Notes: (1) The DWA implementation allows Sels to be used with hits up to 31 pixels from the origin, either horizontally or vertically. Larger Sels can be used if decomposed into a set of operations with Sels not exceeding 63 pixels in either width or height (and with the origin as close to the center of the Sel as possible). (2) This returns the decomposition of a linear Sel of length into a set of
Sels of length 63 plus an extra Sel of length . (3) For notation, let w == , n ==
, and e == . We have 1 < e < 63.

Then if w < 64, we have n = 0 and e = w. The general formula for w > 63 is: w = 63 + (n - 1) * 62 + (e - 1)

Where did this come from? Each successive convolution with a Sel of length L adds a total length (L - 1) to w. This accounts for using 62 for each additional Sel of size 63, and using (e - 1) for the additional Sel of size e.

Solving for n and e for w > 63: n = 1 + Int((w - 63) / 62) e = w - 63 - (n - 1) * 62 + 1

The extra part is decomposed into two factors f1 and f2, and the actual size of the extra part is e' = f1 * f2 Then the actual width is: w' = 63 + (n - 1) * 62 + f1 * f2 - 1

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

pixCloseBrickDwa()

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) This is a 'safe' closing; we add an extra border of 32 OFF pixels for the standard asymmetric b.c. (2) These implement 2D brick Sels, using linear Sels generated with selaAddBasic(). (3) A brick Sel has hits for all elements. (4) The origin of the Sel is at (x, y) = (hsize/2, vsize/2) (5) Do separably if both hsize and vsize are > 1. (6) It is necessary that both horizontal and vertical Sels of the input size are defined in the basic sela. (7) Note that we must always set or clear the border pixels before each operation, depending on the the b.c. (symmetric or asymmetric). (8) 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) (9) For clarity, if the case is known, use these patterns: (a) pixd = pixCloseBrickDwa(NULL, pixs, ...); (b) pixCloseBrickDwa(pixs, pixs, ...); (c) pixCloseBrickDwa(pixd, pixs, ...); (10) The size of the result is determined by pixs. (11) If either linear Sel is not found, this calls the appropriate decomposible function.

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

pixCloseCompBrickDwa()

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) This implements a separable composite safe closing with 2D brick Sels. (2) For efficiency, it may decompose each linear morphological operation into two (brick + comb). (3) A brick Sel has hits for all elements. (4) The origin of the Sel is at (x, y) = (hsize/2, vsize/2) (5) Do separably if both hsize and vsize are > 1. (6) It is necessary that both horizontal and vertical Sels of the input size are defined in the basic sela. (7) 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) (8) For clarity, if the case is known, use these patterns: (a) pixd = pixCloseCompBrickDwa(NULL, pixs, ...); (b) pixCloseCompBrickDwa(pixs, pixs, ...); (c) pixCloseCompBrickDwa(pixd, pixs, ...); (9) The size of pixd is determined by pixs. (10) 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* pixCloseCompBrickExtendDwa ( PIX pixd,
PIX pixs,
l_int32  hsize,
l_int32  vsize 
)

pixCloseCompBrickExtendDwa()

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

(1) 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) (2) There is no need to call this directly: pixCloseCompBrickDwa() calls this function if either brick dimension exceeds 63.

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

pixDilateBrickDwa()

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) These implement 2D brick Sels, using linear Sels generated with selaAddBasic(). (2) A brick Sel has hits for all elements. (3) The origin of the Sel is at (x, y) = (hsize/2, vsize/2) (4) Do separably if both hsize and vsize are > 1. (5) It is necessary that both horizontal and vertical Sels of the input size are defined in the basic sela. (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 = pixDilateBrickDwa(NULL, pixs, ...); (b) pixDilateBrickDwa(pixs, pixs, ...); (c) pixDilateBrickDwa(pixd, pixs, ...); (8) The size of pixd is determined by pixs. (9) If either linear Sel is not found, this calls the appropriate decomposible function.

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

pixDilateCompBrickDwa()

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) These implement a separable composite dilation with 2D brick Sels. (2) For efficiency, it may decompose each linear morphological operation into two (brick + comb). (3) A brick Sel has hits for all elements. (4) The origin of the Sel is at (x, y) = (hsize/2, vsize/2) (5) Do separably if both hsize and vsize are > 1. (6) It is necessary that both horizontal and vertical Sels of the input size are defined in the basic sela. (7) 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) (8) For clarity, if the case is known, use these patterns: (a) pixd = pixDilateCompBrickDwa(NULL, pixs, ...); (b) pixDilateCompBrickDwa(pixs, pixs, ...); (c) pixDilateCompBrickDwa(pixd, pixs, ...); (9) The size of pixd is determined by pixs. (10) 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* pixDilateCompBrickExtendDwa ( PIX pixd,
PIX pixs,
l_int32  hsize,
l_int32  vsize 
)

pixDilateCompBrickExtendDwa()

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) Ankur Jain suggested and implemented extending the composite DWA operations beyond the 63 pixel limit. This is a simplified and approximate implementation of the extension. This allows arbitrary Dwa morph operations using brick Sels, by decomposing the horizontal and vertical dilations into a sequence of 63-element dilations plus a dilation of size between 3 and 62. (2) The 63-element dilations are exact, whereas the extra dilation is approximate, because the underlying decomposition is in pixDilateCompBrickDwa(). See there for further details. (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) There is no need to call this directly: pixDilateCompBrickDwa() calls this function if either brick dimension exceeds 63.

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

pixErodeBrickDwa()

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) These implement 2D brick Sels, using linear Sels generated with selaAddBasic(). (2) A brick Sel has hits for all elements. (3) The origin of the Sel is at (x, y) = (hsize/2, vsize/2) (4) Do separably if both hsize and vsize are > 1. (5) It is necessary that both horizontal and vertical Sels of the input size are defined in the basic sela. (6) Note that we must always set or clear the border pixels before each operation, depending on the the b.c. (symmetric or asymmetric). (7) 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) (8) For clarity, if the case is known, use these patterns: (a) pixd = pixErodeBrickDwa(NULL, pixs, ...); (b) pixErodeBrickDwa(pixs, pixs, ...); (c) pixErodeBrickDwa(pixd, pixs, ...); (9) The size of the result is determined by pixs. (10) If either linear Sel is not found, this calls the appropriate decomposible function.

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

pixErodeCompBrickDwa()

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) These implement a separable composite erosion with 2D brick Sels. (2) For efficiency, it may decompose each linear morphological operation into two (brick + comb). (3) A brick Sel has hits for all elements. (4) The origin of the Sel is at (x, y) = (hsize/2, vsize/2) (5) Do separably if both hsize and vsize are > 1. (6) It is necessary that both horizontal and vertical Sels of the input size are defined in the basic sela. (7) 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) (8) For clarity, if the case is known, use these patterns: (a) pixd = pixErodeCompBrickDwa(NULL, pixs, ...); (b) pixErodeCompBrickDwa(pixs, pixs, ...); (c) pixErodeCompBrickDwa(pixd, pixs, ...); (9) The size of pixd is determined by pixs. (10) 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* pixErodeCompBrickExtendDwa ( PIX pixd,
PIX pixs,
l_int32  hsize,
l_int32  vsize 
)

pixErodeCompBrickExtendDwa()

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) See pixDilateCompBrickExtendDwa() for usage. (2) There is no need to call this directly: pixErodeCompBrickDwa() calls this function if either brick dimension exceeds 63.

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

pixOpenBrickDwa()

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) These implement 2D brick Sels, using linear Sels generated with selaAddBasic(). (2) A brick Sel has hits for all elements. (3) The origin of the Sel is at (x, y) = (hsize/2, vsize/2) (4) Do separably if both hsize and vsize are > 1. (5) It is necessary that both horizontal and vertical Sels of the input size are defined in the basic sela. (6) Note that we must always set or clear the border pixels before each operation, depending on the the b.c. (symmetric or asymmetric). (7) 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) (8) For clarity, if the case is known, use these patterns: (a) pixd = pixOpenBrickDwa(NULL, pixs, ...); (b) pixOpenBrickDwa(pixs, pixs, ...); (c) pixOpenBrickDwa(pixd, pixs, ...); (9) The size of the result is determined by pixs. (10) If either linear Sel is not found, this calls the appropriate decomposible function.

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

pixOpenCompBrickDwa()

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) These implement a separable composite opening with 2D brick Sels. (2) For efficiency, it may decompose each linear morphological operation into two (brick + comb). (3) A brick Sel has hits for all elements. (4) The origin of the Sel is at (x, y) = (hsize/2, vsize/2) (5) Do separably if both hsize and vsize are > 1. (6) It is necessary that both horizontal and vertical Sels of the input size are defined in the basic sela. (7) 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) (8) For clarity, if the case is known, use these patterns: (a) pixd = pixOpenCompBrickDwa(NULL, pixs, ...); (b) pixOpenCompBrickDwa(pixs, pixs, ...); (c) pixOpenCompBrickDwa(pixd, pixs, ...); (9) The size of pixd is determined by pixs. (10) 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* pixOpenCompBrickExtendDwa ( PIX pixd,
PIX pixs,
l_int32  hsize,
l_int32  vsize 
)

pixOpenCompBrickExtendDwa()

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

(1) 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) (2) There is no need to call this directly: pixOpenCompBrickDwa() calls this function if either brick dimension exceeds 63.