13 #ifndef ML_CLUSTER_ALGORITHM_H
14 #define ML_CLUSTER_ALGORITHM_H
35 similarityToleranceIntensities = 0;
36 similarityToleranceVectors = 0.98;
38 contentImage =
nullptr;
40 useBackgroundValue =
true;
42 useImageValueAsUserData =
false;
44 progressCBUserData =
nullptr;
61 template <
typename CLUSTERVOXELTYPE,
typename DerivedAlgorithm>
class ClusterAlgorithm;
64 template <
typename CLUSTERVOXELTYPE,
typename DerivedAlgorithm>
72 _algorithm = algorithm;
87 OrderedProcessAllPagesHandler::calculateOutputImageProperties(image);
102 _inImageExtent = imageExt;
107 if ((inputIndex == 0) || (inputIndex == 1 && _useMask))
109 return outputSubImageBox;
124 _algorithm->storeNextSlice(images[0]);
125 _error = _algorithm->processSlice(images[0].getOrigin().z, _inImageExtent, maskImage);
165 enum { _NR_OF_SUBIMAGES = 2 } NumInImagesEnum;
204 template <
typename CLUSTERVOXELTYPE,
typename DerivedAlgorithm>
220 template <
typename CLUSTERVOXELTYPE,
typename DerivedAlgorithm>
235 return static_cast<DerivedAlgorithm*
>(
this)->calcClustersForSlices();
249 CLUSTERVOXELTYPE currentValue,
253 CLUSTERVOXELTYPE neighborVoxel = DerivedAlgorithm::getVoxel(neighborVoxelPtr);
254 const bool isInToleranceFlag =
static_cast<DerivedAlgorithm*
>(
this)->isInTolerance(neighborVoxel, currentValue);
255 if (isInToleranceFlag)
257 currentClusterRef = mergeClusterReference(x, y, z, currentClusterRef);
259 return currentClusterRef;
264 return static_cast<CLUSTERVOXELTYPE
>(backgroundValue);
272 setInSliceVoxelType(_parameters.contentImage->getDataType());
274 ImageVector inputImageExtent = _parameters.contentImage->getImageExtent();
279 MLErrorCode errorCode = _clusters->init(inputImageExtent.
x, inputImageExtent.
y, inputImageExtent.
z);
283 if ((_parameters.neighborhoodRelation ==
NBH_2D_4_XY) || (_parameters.neighborhoodRelation ==
NBH_2D_8_XY))
285 _clusters->setUse2DNeighborhood();
288 const bool useMask = _parameters.maskImage !=
nullptr;
290 if (!Host::getDefaultHost().getUseClassicHost())
293 handler.
setParameters(useMask, _currentSlices[0].getDataType());
295 std::vector<PagedImage*> images;
296 images.push_back(_parameters.contentImage);
299 images.push_back(_parameters.maskImage);
302 errorCode = Host::getDefaultHost().processAllPagesWithInputImages(images, handler,
SubImageBox(), _parameters.progressCB, _parameters.progressCBUserData);
313 errorCode = loadNextSlice(zi, inputImageExtent);
316 errorCode = loadMaskSlice(inMaskSlice, zi, inputImageExtent);
321 errorCode = processSlice(zi, inputImageExtent, inMaskSlice);
333 _clusters->calcClusterSizes(userDataParameters);
349 const MLint xres = inputImageExtent.
x;
350 const MLint yres = inputImageExtent.
y;
352 const ClusterVoxelType backgroundValue = DerivedAlgorithm::convertBackgroundValue(_parameters.backgroundValue);
355 MLTypeData* previousSliceInternalPtr =
reinterpret_cast<MLTypeData*
>(_currentSlices[0].getData());
356 const MLDataType dataType = _currentSlices[1].getDataType();
357 size_t dataTypeSize =
MLSizeOf(dataType);
361 size_t xoffset = dataTypeSize;
362 size_t yoffset = dataTypeSize * xres;
364 const bool useMask = _parameters.maskImage !=
nullptr;
365 const bool useBackgroundValue = _parameters.useBackgroundValue;
368 for (
MLint yi = 0; yi < yres; yi++)
370 for (
MLint xi = 0; xi < xres; xi++)
373 MLTypeData* previousSlicePtr = previousSliceInternalPtr;
377 sliceInternalPtr += dataTypeSize;
378 previousSliceInternalPtr += dataTypeSize;
381 CLUSTERVOXELTYPE currentValue = DerivedAlgorithm::getVoxel(slicePtr);
386 MLint8 maskValue = *maskPtr++;
394 if (useBackgroundValue && (currentValue == backgroundValue))
400 MLuint currentClusterRef = 0;
405 currentClusterRef = updateClusterRefForNeighbor(slicePtr - xoffset, xi - 1, yi, zi, currentValue, currentClusterRef);
409 currentClusterRef = updateClusterRefForNeighbor(slicePtr - yoffset, xi, yi - 1, zi, currentValue, currentClusterRef);
412 switch (_parameters.neighborhoodRelation)
415 if ((xi > 0) && (yi > 0))
417 currentClusterRef = updateClusterRefForNeighbor(slicePtr - xoffset - yoffset, xi - 1, yi - 1, zi, currentValue, currentClusterRef);
419 if ((xi<xres - 1) && (yi>0))
421 currentClusterRef = updateClusterRefForNeighbor(slicePtr + xoffset - yoffset, xi + 1, yi - 1, zi, currentValue, currentClusterRef);
428 if ((xi > 0) && (yi > 0) && (zi > 0))
430 currentClusterRef = updateClusterRefForNeighbor(previousSlicePtr - xoffset - yoffset, xi - 1, yi - 1, zi - 1, currentValue, currentClusterRef);
432 if ((xi<xres - 1) && (yi>0) && (zi > 0))
434 currentClusterRef = updateClusterRefForNeighbor(previousSlicePtr + xoffset - yoffset, xi + 1, yi - 1, zi - 1, currentValue, currentClusterRef);
436 if ((xi > 0) && (yi<yres - 1) && (zi>0))
438 currentClusterRef = updateClusterRefForNeighbor(previousSlicePtr - xoffset + yoffset, xi - 1, yi + 1, zi - 1, currentValue, currentClusterRef);
440 if ((xi<xres - 1) && (yi<yres - 1) && (zi>0))
442 currentClusterRef = updateClusterRefForNeighbor(previousSlicePtr + xoffset + yoffset, xi + 1, yi + 1, zi - 1, currentValue, currentClusterRef);
446 if ((xi>0) && (yi > 0))
448 currentClusterRef = updateClusterRefForNeighbor(slicePtr - xoffset - yoffset, xi - 1, yi - 1, zi, currentValue, currentClusterRef);
450 if ((xi<xres - 1) && (yi>0))
452 currentClusterRef = updateClusterRefForNeighbor(slicePtr + xoffset - yoffset, xi + 1, yi - 1, zi, currentValue, currentClusterRef);
454 if ((zi > 0) && (xi > 0))
456 currentClusterRef = updateClusterRefForNeighbor(previousSlicePtr - xoffset, xi - 1, yi, zi - 1, currentValue, currentClusterRef);
458 if ((zi > 0) && (xi<xres - 1))
460 currentClusterRef = updateClusterRefForNeighbor(previousSlicePtr + xoffset, xi + 1, yi, zi - 1, currentValue, currentClusterRef);
462 if ((zi>0) && (yi > 0))
464 currentClusterRef = updateClusterRefForNeighbor(previousSlicePtr - yoffset, xi, yi - 1, zi - 1, currentValue, currentClusterRef);
466 if ((zi > 0) && (yi<yres - 1))
468 currentClusterRef = updateClusterRefForNeighbor(previousSlicePtr + yoffset, xi, yi + 1, zi - 1, currentValue, currentClusterRef);
474 currentClusterRef = updateClusterRefForNeighbor(previousSlicePtr, xi, yi, zi - 1, currentValue, currentClusterRef);
489 if (currentClusterRef == 0)
493 if (_parameters.useImageValueAsUserData)
495 imageValue = DerivedAlgorithm::getVoxelAsDouble(slicePtr);
498 currentClusterRef = _clusters->getNewReference(imageValue);
500 _clusters->setClusterRef(xi, yi, zi, currentClusterRef);
@ CLUSTER_MODE_IdenticalIntensities
Interface class for clustering algorithms.
Clusters * _clusters
Result clusters.
ClusterAlgorithmBase(const ComputeClusterParameters ¶meters, Clusters *clusters)
Constructor to be used.
MLErrorCode loadMaskSlice(TSubImage< MLint8 > &slice, MLint sliceNr, const ImageVector &inImgExt) const
Gets current slice of the mask image.
virtual ~ClusterAlgorithmBase()
Default virtual destructor.
void freeInSliceData()
Releases memory of input image slices.
MLErrorCode loadNextSlice(MLint sliceNr, const ImageVector &inImgExt)
Gets next image data.
void setResultFlag(bool result)
Sets internal result flag to result.
MLuint mergeClusterReference(MLint x, MLint y, MLint z, MLuint currClusterRef)
Merges a cluster reference currClusterRef for position (x,y,z).
ComputeClusterParameters _parameters
void storeNextSlice(SubImage &slice)
Sets next image data, expects the data to be managed by memory manager.
bool hasResults() const
Returns whether getCluster() and getClusterOfVoxel() contains cluster data.
void setInSliceVoxelType(MLDataType dt)
Sets voxel type of input slices.
Type specific implementations of the interface class for clustering algorithms.
static CLUSTERVOXELTYPE convertBackgroundValue(MLdouble backgroundValue)
CLUSTERVOXELTYPE ClusterVoxelType
The used type of the voxels, needed by derived classes.
MLuint updateClusterRefForNeighbor(void *neighborVoxelPtr, MLint x, MLint y, MLint z, CLUSTERVOXELTYPE currentValue, MLuint currentClusterRef)
Checks if neighbor at position x,y,z belongs to the same cluster given by currentClusterRef.
MLErrorCode runClustering()
MLErrorCode processSlice(MLint zi, const ImageVector &inputImageExtent, TSubImage< MLint8 > &inMaskSlice)
MLErrorCode calcClustersForSlices()
Template applying cluster calculations for one slice.
ClusterAlgorithm(const ComputeClusterParameters ¶meters, Clusters *clusters)
Constructor to be used.
ClusterHandler that is used to provide slice-by-slice data to the cluster algorithm.
MLErrorCode processTiles(SubImage *images) override
Reimplement this method to perform the processing, return ML_RESULT_OK if processing should go on; ot...
void calculateOutputImageProperties(PagedImage *image) override
Reimplement this method to specify the virtual output image's data type/size/page extent.
SubImageBox calculateInputSubImageBox(int inputIndex, const SubImageBox &outputSubImageBox) override
Reimplement this method to specify the input image box for the input images.
void setParameters(bool useMask, MLDataType type)
Stores all parameters that are needed to call the algorithm.
MLErrorCode getErrorCode() const
ClusterHandler(ClusterAlgorithm< CLUSTERVOXELTYPE, DerivedAlgorithm > *algorithm)
Structure computes and holds all cluster information. For internal use.
ImageVector getImageExtent() const
Returns the extent of the (sub)image.
A ProcessAllPages handler that offers ordered tile delivery on any number of input images.
The class PagedImage, representing a fragmented image that manages properties and data of an image lo...
MLEXPORT void setInputSubImageDataType(int inputIndex, MLDataType dataType)
Sets the dataType for the given inputIndex.
MLEXPORT void setPageExtent(const ImageVector &pageExtent)
Sets the extents of the pages to pageExtent.
MLEXPORT void setDataType(MLDataType dataType) override
Sets the type of data to dataType. Overridden to perform access check.
virtual MLEXPORT void setImageExtent(const ImageVector &extent)
Sets the extents of the image to extent. The list of valid pages and its content are cleared.
MLEXPORT void setInputSubImagesAreReadOnly(bool readOnly=true)
Sets the read-only flag for all input images.
This class manages/represents a rectangular 6D image region that is organized linearly in memory.
This template class manages/represents a rectangular 6D image region in memory that is organized line...
const DATATYPE * getData() const
Returns the memory address of the image region. Overloads methods from SubImage.
ComponentType c
Color component of the vector.
ComponentType t
Time component of the vector.
ComponentType u
Unit/Modality/User component of the vector.
ComponentType z
Z component of the vector.
ComponentType x
X component of the vector.
ComponentType y
Y component of the vector.
#define ML_DISALLOW_COPY_AND_ASSIGN(className)
Defines basic macros.
MLEXPORT size_t MLSizeOf(MLDataType dataType)
Returns the size of the data type dataType in bytes.
MLint32 MLDataType
MLDataType.
@ MLint8Type
Enumerator for the signed 8-bit ML integer type.
#define ML_PROGRAMMING_ERROR
A case occurred that should not appear and there are a variety of reasons, typically it is a programm...
MLint32 MLErrorCode
Type of an ML Error code.
#define ML_RESULT_OK
No error. Everything seems to be okay.
void MLRequestProgressCB(void *usrData, double progress)
MLuint64 MLuint
An unsigned ML integer type with at least 64 bits used for index calculations on very large images ev...
unsigned char MLTypeData
This is the pointer type used to point to the data of MLType data instances.
MLint64 MLint
A signed ML integer type with at least 64 bits used for index calculations on very large images even ...
TSubImageBox< MLint > SubImageBox
Defines the standard SubImageBox type used in the ML. Its size varies with the size of the MLint type...
Cluster user data parameters.
MLdouble voxelSizeInMilliliters
bool useImageValueAsUserData
Structure to hold parameters for cluster computation.
CLUSTER_MODE_TYPE clusterMode
ComputeClusterParameters()
MLdouble similarityToleranceIntensities
void * progressCBUserData
bool useImageValueAsUserData
MLRequestProgressCB * progressCB
MLdouble similarityToleranceVectors
PagedImage * contentImage
NBH_TYPE neighborhoodRelation