IPSDK 0.2
IPSDK : Image Processing Software Development Kit
Seeded Distance Map 2dSee full documentation
distImg,distWeight2dseededDistanceMap2dImg (inBinImg,inBinSeedImg)
distImg,distWeight2dseededDistanceMap2dImg (inBinImg,inBinSeedImg,pixelXSize,pixelYSize,neighborhood2d)
DistWeight2dseededDistanceMap2dImg (inBinImg,inBinSeedImg,pixelXSize,pixelYSize,neighborhood2d,outDistImg)
distImg,distWeight2dseededDistanceMap2dImg (inBinImg,inBinSeedImg,maxDistance)
distImg,distWeight2dseededDistanceMap2dImg (inBinImg,inBinSeedImg,pixelXSize,pixelYSize,neighborhood2d,maxDistance)
DistWeight2dseededDistanceMap2dImg (inBinImg,inBinSeedImg,pixelXSize,pixelYSize,neighborhood2d,maxDistance,outDistImg)

Detailed Description

seeded distance map transform of an input binary image according to a seeded image

2d seeded distance map algorithm allows to compute the distance to the closest seeded pixel in a region for each pixel of this region, according to the given pixel size. As in Generic Seeded Distance Map 2d, the region is defined by a binary image with pixel intensities set to 1. The seeded pixels are defined by a seeded image with pixel intensities set to 1. If the parameter $ maxDistance $ is provided, the propagation is constrained so that it stops when the distance is higher than the $ maxDistance $ value.

The resulting image buffer type must be one of the following :

Output image values are given by :

\[ OutDistImg[x, y] = \left\{ \begin{array}{rl} 0 &\mbox{\text{if } InBinImg[x, y] = 0} \\ 1 &\mbox{\text{if } InBinImg[x, y] \text{is a seeded pixel}} \\ \min\limits_{(x_d, y_d) \in \aleph \wedge InBinImg[x_d, y_d] > 0}{\left( InBinImg[x_d, y_d]+\omega_d \right)} &\mbox{otherwise} \end{array} \right. \]

Where $\aleph$ is the pixel's neighbourhood, $d$ is the set of directions allowed by $\aleph$ and can be lateral (along the x-axis), axial (along the y-axis) or diagonal. $\omega_d$ is the weight corresponding to the direction $d$.

For a real output distance image, the weighting coefficients are set to $pixelXSize$ and $pixelYSize$ along the x ( $\omega_x$) and y ( $\omega_y$) directions respectively and the diagonal weighting coefficient is set to $\omega_{xy} = \sqrt{pixelXSize^2 + pixelXSize^2}$.

However, in the case of integer output, the coefficients are calculated in order to achieve the calculation with a good compromise between accuracy and computation efficiency [1]. In this case, the weights $\omega_x$, $\omega_y$ and $\omega_{xy}$ are calculated as described in the following algorithm :

1- For simplicity in the notation, let $(W, H) = (pixelXSize, pixelYSize)$ be the size of a pixel.

2- Compute the real coefficient along the y axis:

\[ d_y = \frac{-2 H + 2 H \sqrt{1+\lambda}}{\lambda} \]

with

\[ \lambda = \frac{ \sqrt{W^2 + H^2 } - H}{W^2} \]

3- Compute the other coefficients :

\begin{eqnarray*} d_x & = & \frac{ W d_y }{H} \\ d_{xy} & = & \frac{ \sqrt{W^2 + H^2} d_y }{H} \end{eqnarray*}

4- Compute the integer approximation $\left\lbrace \omega_x, \omega_y, \omega_{xy} \right\rbrace$ of the coefficients $\left\lbrace d_x, d_y, d_{xy} \right\rbrace$.

a- For this, we assume that que maximum calculable distance is $Dim \times \omega_{xy}$, where $Dim$ is the maximum between the output image width and the output image height.

b- An integer scale factor $N$ can then be computed. It must be large enough to allow a good approximation to the Euclidian distance and small enough to avoid overflow due to the output image type limitation.

\[ N \leq \frac{2^b}{Dim \times d_{xy}} \]

Where $b$ is the number of bits used to encode the each element of the distance map (e.g. $b = 16$ for an unsigned short distance map).

c- The integer distance weighting coefficients can now be calculated as follows :

\begin{eqnarray*} \omega_x & = & round \left( N \times d_x \right) \\ \omega_y & = & round \left( N \times d_y \right) \\ \omega_{xy} & = & round \left( N \times d_{xy} \right) \end{eqnarray*}

5- Finally, the original scale must be retrieved and the resulting image is divided by $N$.

Note
If the user defines a 4-connexity with the ipsdk::eNeighborhood2dType parameter, $\omega_{xy}$ is set to 0 and the neighbourhood along the xy-direction are not used in the distance calculation.

Here is an example of a 2d seeded distance map computation applied to a binary input image with a real result image. The seeds are displayed in red in the bottom sub-images and the neighborhood was set to 8-connexity :

genericSeededDistanceMap2dImg.png

References

[1] "Contribution a la comparaison d'images pour l'evaluation des traitements, la reconnaissance de formes et l'indexation des sequences d'images", Didier COQUIN, HDR, 2007

Example of Python code :

Example imports

import PyIPSDK
import PyIPSDK.IPSDKIPLAdvancedMorphology as advmorpho

Code Example

# opening of input images
inImg = PyIPSDK.loadTiffImageFile(inputImgPath)
inSeedsImg = PyIPSDK.loadTiffImageFile(inputSeedsImgPath)
# seeded distance map 2d computation
outDistImg, outDistWeight2d = advmorpho.seededDistanceMap2dImg(inImg, inSeedsImg)
# retrieve computed coefficients
xWeight = outDistWeight2d.xWeight
yWeight = outDistWeight2d.yWeight
xyWeight = outDistWeight2d.xYWeight

Example of C++ code :

Example informations

Header file

#include <IPSDKIPL/IPSDKIPLAdvancedMorphology/Processor/SeededDistanceMap2dImg/SeededDistanceMap2dImg.h>

Code Example

// opening input image
ImagePtr pInBinImg = loadTiffImageFile(inputImgPath);
// opening seed input image
ImagePtr pInSeedImg = loadTiffImageFile(inputSeedImgPath);
// Define the size of the pixels
const ipReal64 pixelXSize = 1.;
const ipReal64 pixelYSize = 1.;
// define output image geometry
ImageGeometryPtr pDistGeometry = geometry2d(outputImageBufferType,
pInBinImg->getSizeX(),
pInBinImg->getSizeY());
// creation of output image
boost::shared_ptr<MemoryImage> pOutDistImg(boost::make_shared<MemoryImage>());
pOutDistImg->init(*pDistGeometry);
// compute distance map on input image
DistWeight2dPtr pDistWeight2d = seededDistanceMap2dImg(pInBinImg, pInSeedImg, pixelXSize, pixelYSize, neighborhood2dType, pOutDistImg);
// retrieve computed weights
const ipReal64 XWeight = pDistWeight2d->getValue<DistWeight2d::XWeight>();
const ipReal64 YWeight = pDistWeight2d->getValue<DistWeight2d::YWeight>();
const ipReal64 XYWeight = pDistWeight2d->getValue<DistWeight2d::XYWeight>();