IPSDK 0.2
IPSDK : Image Processing Software Development Kit
Cylinder unrolling algorithmSee full documentation
imageunrollCylinderImg (inImg3d,inOutputImgSizeX,center2d,radius,theta0,interpolationPolicy)

Detailed Description

Unrolls into a 2D image a cylinder contained in a 3D image.

Considering:

The UnrollCylinderImg algorithm computes the 2D array of interpolated intensities of voxels of input image along the surface of the cylinder. Each row of the resulting 2D array corresponds to a XY plan of the input 3D image. So the 2D array contains $ InImSizeZ $ rows, and each row contains $inOutputImSizeX$ values, that correspond to the intensities computed on regularly spaced samples along a circle (intersection between the cylinder and the current XY plan) of center $ InCenter2d $ and of radius $ InRadius $ . As the coordinates of these samples may be floating values, their intensities are computed interpolating their closest voxels in current XY plan. The user can choose between 3 types of interpolations ( $ interpolationPolicy$ attribute): nearest neighbour, linear and cubic.

Values of the computed 2D array are finally returned in the 2D output image $ OutImg2d $.

The following figures illustrate how the pixels of the output 2D image are computed from the input 3D image and from the cylinder:

UnrollCylinderImg_figure1.png
Figure 1 - The input image on this figure (on the left) is a 3D 5x4x5 image, represented as a grey grid. Properties of the cylinder are {InCenter2d=(2.75, 2.5), radius=1.5}; red dots correspond to the positions at which intensities of 3D images are evaluated to generate the 2D output image (on the right) with an expected width of 5 pixels.
UnrollCylinderImg_figure2.png
Figure 2 - Focusing on a single XY plan of the 3D input image, we see that the 5 sample points P0, ..., P4 are regularly spaced on the circle of properties {InCenter2d, radius); angle between x-axis and line passing through circle center and P0 equals to theta0 (see description below); to each XY plan in input image (see on the left) is associated a row in output image (see on the right).

By default, the surface of the defined cylinder has no thickness, but optionnally, a non-null half-thickness can be specified. In that case, for each one of the $ OutImSizeX \times InImSizeZ $ samples, the user can choose to get the mean, the minimum or the maximum of the $ 2 \times InHalfThickness + 1 $ sub-samples along the thickness of the surface.

Mathematically, values of the output images are defined as follows, depending on the thickness of the cylinder and on the retained integration type (mean, minimum or maximum):

Here is an example of application of UnrollCylinderImg algorithm; the input image is a synthesis image generated by artificially rolling the 2D Lena image around a cylinder in an originally black 3D image; to make image reading easier on the snapshot below on the left, black pixels are masked, so that we can see the intensities of the cylinder surface; the result of algorithm application is displayed on the right:

UnrollCylinerImg.png

Example of Python code :

Example imports

import PyIPSDK
import PyIPSDK.IPSDKIPLGeometricTransform as gtrans

Code Example

# initialize input parameters:
# we want to unroll, from a 3D image loaded from file path 'inputImgFilePath', a cylinder with axis at (150, 149) and radius=50
# into a 2d image of x-size 400;
# theta0 is set to 0 and linear interpolation is used
inImg = PyIPSDK.loadTiffImageFile(inputImgFilePath);
centerX = 150.0
centerY = 149.0
radius = 50.0
theta0 = 0.0
interpolationPolicy = PyIPSDK.eInterpolationPolicy.eIP_Linear
outImg = PyIPSDK.createImage(inImg.getBufferType(), 400, inImg.getSizeZ())
gtrans.unrollCylinderImg(inImg, PyIPSDK.createCoords2d(centerX, centerY), radius, theta0, interpolationPolicy, outImg)

Example of C++ code :

Example informations

Header file

#include <IPSDKIPL/IPSDKIPLGeometricTransform/Processor/UnrollCylinderImg/UnrollCylinderImg.h>

Code Example

// initialize input parameters:
// we want to unroll, from a 3D image loaded from file path 'inputImgFilePath', a cylinder with axis at (150, 149) and radius=50
// into a 2d image of x-size 400;
// theta0 is set to 0 and linear interpolation is used
ImagePtr pInImg = loadTiffImageFile(inputImgFilePath);
const ipReal64 centerX = 150.0;
const ipReal64 centerY = 149.0;
const ipReal64 radius = 50.0;
const ipReal64 theta0 = .0;
boost::shared_ptr<MemoryImage> pOutImg = boost::make_shared<MemoryImage>();
pOutImg->init(*geometry2d(pInImg->getBufferType(), 400, pInImg->getSizeZ()));
gtrans::unrollCylinderImg(
pInImg,
createCoords2d(centerX, centerY),
radius,
theta0,
interpolationPolicy,
pOutImg);