image = | cannySurfaces3dImg (inGxImg3d,inGyImg3d,inGzImg3d,thresholds) |
Detects surfaces in a 3d image using Canny's algorithm.
Detects boundary surfaces in a 3d image using Canny's algorithm, and generates an output binary image, with voxels associated to the found surfaces in white, and the rest in black.
Given 3 gradient images (computed, for instance, thanks to Sobel Gradient 3d or Gaussian Gradient 3d), respectively along x (Gx image), y (Gy image) and z-axis (Gz image), Canny surface detector can be decomposed into the following steps:
- from Gx, Gy and Gz images, magnitude and orientation of gradient is computed
- non-maxima suppression: for each voxel in the image of gradient magnitude, if the pixel value is greater than the values of its 2 neighbours along the gradient direction, then the pixel is marked as "to be processed"; otherwise, it is marked as "not a boundary surface". This step prevents from having too thick boundary surfaces.
- for all voxels tagged "to be processed", mark as:
- "not a boundary surface" voxels whose gradient magnitude value is lower than low threshold value specified by the user
- "strong boundary surface" voxels whose gradient magnitude value is higher than high threshold value specified by the user
- "perhaps a boundary surface" voxels whose gradient magnitude value is between low and high threshold values
- process voxels tagged "perhaps a boundary surface": a voxel tagged "perhaps a boundary surface" is a strong boundary surface if it is directly or indirectly (ie. there exists a path of connected voxels tagged "perhaps a boundary surface" that link the current voxel to a "strong
boundary surface" voxel) connected to a "strong boundary surface" voxel. Otherwise it is affected the "not a boundary surface" value.
See 2d Canny edge detector for an illustration of Canny edge detection applied to a 2d image.
Example of Python code :
Example imports
import PyIPSDK
import PyIPSDK.IPSDKIPLFeatureDetection as fd
import PyIPSDK.IPSDKIPLFiltering as filter
Code Example
inImg = PyIPSDK.loadTiffImageFile(inputImgPath)
inImg = filter.gaussianSmoothing3dImg(inImg, 1.0);
gxImg, gyImg, gzImg = filter.sobelGradient3dImg(inImg, PyIPSDK.eSobelKernelType.eSKT_SobelHalfKnlSz1, True)
outImg = fd.cannySurfaces3dImg(gxImg, gyImg, gzImg, PyIPSDK.createCannyThresholds(50, 100))
Example of C++ code :
Example informations
Header file
#include <IPSDKIPL/IPSDKIPLFeatureDetection/Processor/CannySurfaces3dImg/CannySurfaces3dImg.h>
Code Example
ImageGeometryPtr pGradGeometry =
geometry3d(eImageBufferType::eIBT_Real32, pInImg->getSizeX(), pInImg->getSizeY(), pInImg->getSizeZ());
boost::shared_ptr<MemoryImage> pGxImg = boost::make_shared<MemoryImage>();
pGxImg->init(*pGradGeometry);
boost::shared_ptr<MemoryImage> pGyImg = boost::make_shared<MemoryImage>();
pGyImg->init(*pGradGeometry);
boost::shared_ptr<MemoryImage> pGzImg = boost::make_shared<MemoryImage>();
pGzImg->init(*pGradGeometry);
ImageGeometryPtr pOutGeometry =
geometry3d(eImageBufferType::eIBT_Binary, pInImg->getSizeX(), pInImg->getSizeY(), pInImg->getSizeZ());
boost::shared_ptr<MemoryImage> pOutImg = boost::make_shared<MemoryImage>();
pOutImg->init(*pOutGeometry);