Unrolls into a 2D image a cylinder contained in a 3D image.
Considering:
- an input 3D image
of dimensions
,
- a cylinder, entirely inside the input 3D image, with the following properties:
- axis along 3D image z-axis,
- height coinciding with
,
- center with x and y coordinates defined by
attribute and z at
(in other words, projection of cylinder center along z-axis coincides with center of image along z-axis, x and y coordinates are specified by the user),
- a 2D center
and a radius
specified by the user,
- an output image with the following dimensions:
- given x-size
,
- y-size equals to input image z-size,
- a given angle offset
, in radians.
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
rows, and each row contains
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
and of radius
. 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 (
attribute): nearest neighbour, linear and cubic.
Values of the computed 2D array are finally returned in the 2D output image
.
The following figures illustrate how the pixels of the output 2D image are computed from the input 3D image and from the cylinder:
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.
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
samples, the user can choose to get the mean, the minimum or the maximum of the
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):
- null thickness:
with:
an angle offset, in radians, specified by the user,

non-null thickness, mean:
non-null thickness, minimum:
non-null thickness, 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:
Example of Python code :
Example imports
import PyIPSDK
import PyIPSDK.IPSDKIPLGeometricTransform as gtrans
Code Example
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
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,
radius,
theta0,
interpolationPolicy,
pOutImg);