forked from BlueQuartzSoftware/simplnx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FILTER: ITK Projection Filters (BlueQuartzSoftware#1162)
* Maximum, Median, Minimum, Mean Projection Filters * Update documentation, test cases, extraneous code removal * Make Filters conform to the Binary Projection precedent * Added functionality to preserve integrity of input geometry (off by default) Done by creating a new resized geom with only projected data in it * Limit typing and strip RGB/ARGB support --------- Signed-off-by: Michael Jackson <mike.jackson@bluequartz.net> Co-authored-by: Michael Jackson <mike.jackson@bluequartz.net>
- Loading branch information
1 parent
95019fe
commit a2a09b2
Showing
24 changed files
with
2,002 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
src/Plugins/ITKImageProcessing/docs/ITKMaximumProjectionImageFilter.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# ITK Maximum Projection Image Filter (ITKMaximumProjectionImage) | ||
|
||
Maximum projection. | ||
|
||
## Group (Subgroup) | ||
|
||
ITKImageStatistics (ImageStatistics) | ||
|
||
## Description | ||
|
||
This class was contributed to the Insight Journal by Gaetan Lehmann. The original paper can be found at https://www.insight-journal.org/browse/publication/71 | ||
|
||
## Author | ||
|
||
- Gaetan Lehmann. Biologie du Developpement et de la Reproduction, INRA de Jouy-en-Josas, France. | ||
|
||
## See Also | ||
|
||
- [ProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1ProjectionImageFilter.html) | ||
|
||
- [MedianProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1MedianProjectionImageFilter.html) | ||
|
||
- [MinimumProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1MinimumProjectionImageFilter.html) | ||
|
||
- [StandardDeviationProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1StandardDeviationProjectionImageFilter.html) | ||
|
||
- [SumProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1SumProjectionImageFilter.html) | ||
|
||
- [BinaryProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1BinaryProjectionImageFilter.html) | ||
|
||
- [MeanProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1MeanProjectionImageFilter.html) | ||
|
||
% Auto generated parameter table will be inserted here | ||
|
||
## Example Pipelines | ||
|
||
## License & Copyright | ||
|
||
Please see the description file distributed with this plugin. | ||
|
||
## DREAM3D-NX Help | ||
|
||
If you need help, need to file a bug report or want to request a new feature, please head over to the [DREAM3DNX-Issues](https://github.com/BlueQuartzSoftware/DREAM3DNX-Issues/discussions) GitHub site where the community of DREAM3D-NX users can help answer your questions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
src/Plugins/ITKImageProcessing/docs/ITKMedianProjectionImageFilter.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# ITK Median Projection Image Filter (ITKMedianProjectionImage) | ||
|
||
Median projection. | ||
|
||
## Group (Subgroup) | ||
|
||
ITKImageStatistics (ImageStatistics) | ||
|
||
## Description | ||
|
||
This class was contributed to the Insight Journal by Gaetan Lehmann. The original paper can be found at https://www.insight-journal.org/browse/publication/71 | ||
|
||
## Author | ||
|
||
- Gaetan Lehmann. Biologie du Developpement et de la Reproduction, INRA de Jouy-en-Josas, France. | ||
|
||
## See Also | ||
|
||
- [ProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1ProjectionImageFilter.html) | ||
|
||
- [MeanProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1MeanProjectionImageFilter.html) | ||
|
||
- [MinimumProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1MinimumProjectionImageFilter.html) | ||
|
||
- [StandardDeviationProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1StandardDeviationProjectionImageFilter.html) | ||
|
||
- [SumProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1SumProjectionImageFilter.html) | ||
|
||
- [BinaryProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1BinaryProjectionImageFilter.html) | ||
|
||
- [MaximumProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1MaximumProjectionImageFilter.html) | ||
|
||
% Auto generated parameter table will be inserted here | ||
|
||
## Example Pipelines | ||
|
||
## License & Copyright | ||
|
||
Please see the description file distributed with this plugin. | ||
|
||
## DREAM3D-NX Help | ||
|
||
If you need help, need to file a bug report or want to request a new feature, please head over to the [DREAM3DNX-Issues](https://github.com/BlueQuartzSoftware/DREAM3DNX-Issues/discussions) GitHub site where the community of DREAM3D-NX users can help answer your questions. |
43 changes: 43 additions & 0 deletions
43
src/Plugins/ITKImageProcessing/docs/ITKMinimumProjectionImageFilter.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# ITK Minimum Projection Image Filter (ITKMinimumProjectionImage) | ||
|
||
Minimum projection. | ||
|
||
## Group (Subgroup) | ||
|
||
ITKImageStatistics (ImageStatistics) | ||
|
||
## Description | ||
|
||
This class was contributed to the Insight Journal by Gaetan Lehmann. The original paper can be found at https://www.insight-journal.org/browse/publication/71 | ||
|
||
## Author | ||
|
||
- Gaetan Lehmann. Biologie du Developpement et de la Reproduction, INRA de Jouy-en-Josas, France. | ||
|
||
## See Also | ||
|
||
- [ProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1ProjectionImageFilter.html) | ||
|
||
- [MedianProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1MedianProjectionImageFilter.html) | ||
|
||
- [MeanProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1MeanProjectionImageFilter.html) | ||
|
||
- [StandardDeviationProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1StandardDeviationProjectionImageFilter.html) | ||
|
||
- [SumProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1SumProjectionImageFilter.html) | ||
|
||
- [BinaryProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1BinaryProjectionImageFilter.html) | ||
|
||
- [MaximumProjectionImageFilter](https://itk.org/Doxygen/html/classitk_1_1MaximumProjectionImageFilter.html) | ||
|
||
% Auto generated parameter table will be inserted here | ||
|
||
## Example Pipelines | ||
|
||
## License & Copyright | ||
|
||
Please see the description file distributed with this plugin. | ||
|
||
## DREAM3D-NX Help | ||
|
||
If you need help, need to file a bug report or want to request a new feature, please head over to the [DREAM3DNX-Issues](https://github.com/BlueQuartzSoftware/DREAM3DNX-Issues/discussions) GitHub site where the community of DREAM3D-NX users can help answer your questions. |
211 changes: 211 additions & 0 deletions
211
src/Plugins/ITKImageProcessing/src/ITKImageProcessing/Common/ProjectionUtils.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
#pragma once | ||
|
||
#include "simplnx/Common/Result.hpp" | ||
#include "simplnx/Common/Types.hpp" | ||
#include "simplnx/Filter/Actions/CreateImageGeometryAction.hpp" | ||
#include "simplnx/Filter/IFilter.hpp" | ||
|
||
#include "ITKArrayHelper.hpp" | ||
|
||
using namespace nx::core; | ||
|
||
namespace ProjectionUtilities | ||
{ | ||
// uint8, int16, uint16, float32 | ||
using ITKProjectionSupportedOutputTypes = ArrayTypeOptions<false, false, true, true, true, false, false, false, false, true, false>; | ||
|
||
template <class T> | ||
struct FixedOutputTypeHelper | ||
{ | ||
template <class PixelT> | ||
using FilterOutputType = T; | ||
}; | ||
|
||
template <class ArrayOptionsType> | ||
struct RunITKProjectionDataCheckFunctor | ||
{ | ||
template <class FixedOutputType> | ||
auto operator()(const DataStructure& dataStructure, const DataPath& selectedInputArray, const DataPath& imageGeomPath, const DataPath& outputArrayPath) const | ||
{ | ||
return ITK::DataCheck<ArrayOptionsType, FixedOutputTypeHelper<FixedOutputType>::template FilterOutputType>(dataStructure, selectedInputArray, imageGeomPath, outputArrayPath); | ||
} | ||
}; | ||
|
||
template <class ArrayOptionsType, class ITKFunctorType> | ||
struct RunITKProjectionExecuteFunctor | ||
{ | ||
template <class FixedOutputType> | ||
auto operator()(DataStructure& dataStructure, const DataPath& selectedInputArray, const DataPath& imageGeomPath, const DataPath& outputArrayPath, ITKFunctorType&& itkFunctor, | ||
const std::atomic_bool& shouldCancel) const | ||
{ | ||
return ITK::Execute<ArrayOptionsType, FixedOutputTypeHelper<FixedOutputType>::template FilterOutputType>(dataStructure, selectedInputArray, imageGeomPath, outputArrayPath, itkFunctor, | ||
shouldCancel); | ||
} | ||
}; | ||
|
||
template <class ArrayTypeOptions, class FuncT, class FallbackFuncT, class... ArgsT> | ||
auto RunTemplateFunctor(FuncT&& func, FallbackFuncT&& fallback, DataType dataType, ArgsT&&... args) | ||
{ | ||
if constexpr(ArrayTypeOptions::UsingBoolean) | ||
{ | ||
if(dataType == DataType::boolean) | ||
{ | ||
return func.template operator()<bool>(std::forward<ArgsT>(args)...); | ||
} | ||
} | ||
if constexpr(ArrayTypeOptions::UsingInt8) | ||
{ | ||
if(dataType == DataType::int8) | ||
{ | ||
return func.template operator()<int8>(std::forward<ArgsT>(args)...); | ||
} | ||
} | ||
if constexpr(ArrayTypeOptions::UsingInt16) | ||
{ | ||
if(dataType == DataType::int16) | ||
{ | ||
return func.template operator()<int16>(std::forward<ArgsT>(args)...); | ||
} | ||
} | ||
if constexpr(ArrayTypeOptions::UsingInt32) | ||
{ | ||
if(dataType == DataType::int32) | ||
{ | ||
return func.template operator()<int32>(std::forward<ArgsT>(args)...); | ||
} | ||
} | ||
if constexpr(ArrayTypeOptions::UsingInt64) | ||
{ | ||
if(dataType == DataType::int64) | ||
{ | ||
return func.template operator()<int64>(std::forward<ArgsT>(args)...); | ||
} | ||
} | ||
if constexpr(ArrayTypeOptions::UsingUInt8) | ||
{ | ||
if(dataType == DataType::uint8) | ||
{ | ||
return func.template operator()<uint8>(std::forward<ArgsT>(args)...); | ||
} | ||
} | ||
if constexpr(ArrayTypeOptions::UsingUInt16) | ||
{ | ||
if(dataType == DataType::uint16) | ||
{ | ||
return func.template operator()<uint16>(std::forward<ArgsT>(args)...); | ||
} | ||
} | ||
if constexpr(ArrayTypeOptions::UsingUInt32) | ||
{ | ||
if(dataType == DataType::uint32) | ||
{ | ||
return func.template operator()<uint32>(std::forward<ArgsT>(args)...); | ||
} | ||
} | ||
if constexpr(ArrayTypeOptions::UsingUInt64) | ||
{ | ||
if(dataType == DataType::uint64) | ||
{ | ||
return func.template operator()<uint64>(std::forward<ArgsT>(args)...); | ||
} | ||
} | ||
if constexpr(ArrayTypeOptions::UsingFloat32) | ||
{ | ||
if(dataType == DataType::float32) | ||
{ | ||
return func.template operator()<float32>(std::forward<ArgsT>(args)...); | ||
} | ||
} | ||
if constexpr(ArrayTypeOptions::UsingFloat64) | ||
{ | ||
if(dataType == DataType::float64) | ||
{ | ||
return func.template operator()<float64>(std::forward<ArgsT>(args)...); | ||
} | ||
} | ||
return fallback(dataType); | ||
} | ||
|
||
template <class ArrayOptionsType> | ||
IFilter::PreflightResult RunITKProjectionDataCheck(const DataStructure& dataStructure, const DataPath& selectedInputArray, const DataPath& imageGeomPath, const std::string& outputGeomName, | ||
bool performInPlace, const std::string& outputArrayName) | ||
{ | ||
DataPath outputArrayPath = selectedInputArray.replaceName(outputArrayName); | ||
Result<OutputActions> resultOutputActions; | ||
// The input geometry must be preserved, so we will just copy the needed array into newly created output geometry | ||
if(!performInPlace) | ||
{ | ||
DataPath outputGeomPath({outputGeomName}); | ||
|
||
const auto& originalGeometry = dataStructure.getDataRefAs<ImageGeom>(imageGeomPath); | ||
|
||
// Make copy of input geometry | ||
resultOutputActions.value().appendAction(std::make_unique<CreateImageGeometryAction>( | ||
outputGeomPath, originalGeometry.getDimensions().toContainer<CreateImageGeometryAction::DimensionType>(), originalGeometry.getOrigin().toContainer<CreateImageGeometryAction::OriginType>(), | ||
originalGeometry.getSpacing().toContainer<CreateImageGeometryAction::SpacingType>(), originalGeometry.getCellDataPath().getTargetName())); | ||
|
||
outputArrayPath = outputGeomPath.createChildPath(originalGeometry.getCellDataPath().getTargetName()).createChildPath(outputArrayName); | ||
} | ||
|
||
auto fallbackFunc = [](DataType dataType) { | ||
return MakeErrorResult<OutputActions>(-76590, fmt::format("Input {} type is not currently supported. Please reach out to devs if you have a use case.", DataTypeToString(dataType))); | ||
}; | ||
|
||
DataType type = dataStructure.getDataRefAs<IDataArray>(selectedInputArray).getDataType(); | ||
Result<OutputActions> helperOutputActions = RunTemplateFunctor<ITKProjectionSupportedOutputTypes>(RunITKProjectionDataCheckFunctor<ArrayOptionsType>{}, fallbackFunc, type, dataStructure, | ||
selectedInputArray, imageGeomPath, outputArrayPath); | ||
|
||
if(helperOutputActions.invalid()) | ||
{ | ||
return {std::move(helperOutputActions)}; | ||
} | ||
|
||
// Consolidate actions | ||
resultOutputActions.value().actions.insert(resultOutputActions.value().actions.end(), helperOutputActions.value().actions.begin(), helperOutputActions.value().actions.end()); | ||
|
||
return {std::move(resultOutputActions)}; | ||
} | ||
|
||
template <class ArrayOptionsType, class ITKFunctorType> | ||
Result<> RunITKProjectionExecute(DataStructure& dataStructure, const DataPath& selectedInputArray, const DataPath& imageGeomPath, const std::atomic_bool& shouldCancel, | ||
const std::string& outputArrayName, bool performInPlace, ITKFunctorType&& itkFunctor, const std::string& outputImageGeomName) | ||
{ | ||
DataPath outputArrayPath = selectedInputArray.replaceName(outputArrayName); | ||
|
||
DataPath finalImageGeomPath = imageGeomPath; | ||
|
||
if(!performInPlace) | ||
{ | ||
const auto& originalGeometry = dataStructure.getDataRefAs<ImageGeom>(imageGeomPath); | ||
|
||
finalImageGeomPath = DataPath({outputImageGeomName}); | ||
outputArrayPath = finalImageGeomPath.createChildPath(originalGeometry.getCellDataPath().getTargetName()).createChildPath(outputArrayName); | ||
} | ||
|
||
DataType type = dataStructure.getDataRefAs<IDataArray>(selectedInputArray).getDataType(); | ||
|
||
auto fallbackFunc = [](DataType dataType) { | ||
return MakeErrorResult(-76591, fmt::format("Input {} type is not currently supported. Please reach out to devs if you have a use case.", DataTypeToString(dataType))); | ||
}; | ||
|
||
Result<> result = RunTemplateFunctor<ITKProjectionSupportedOutputTypes>(RunITKProjectionExecuteFunctor<ArrayOptionsType, ITKFunctorType>{}, fallbackFunc, type, dataStructure, selectedInputArray, | ||
finalImageGeomPath, outputArrayPath, itkFunctor, shouldCancel); | ||
|
||
if(result.invalid()) | ||
{ | ||
return result; | ||
} | ||
|
||
auto& imageGeom = dataStructure.getDataRefAs<ImageGeom>(finalImageGeomPath); | ||
auto iArrayTupleShape = dataStructure.getDataAs<IArray>(outputArrayPath)->getTupleShape(); | ||
|
||
// Update the Image Geometry with the new dimensions | ||
imageGeom.setDimensions({iArrayTupleShape[2], iArrayTupleShape[1], iArrayTupleShape[0]}); | ||
|
||
// Update the AttributeMatrix with the new tuple shape. THIS WILL ALSO CHANGE ANY OTHER DATA ARRAY THAT IS ALSO | ||
// STORED IN THAT ATTRIBUTE MATRIX | ||
dataStructure.getDataAs<AttributeMatrix>(outputArrayPath.getParent())->resizeTuples(iArrayTupleShape); | ||
|
||
return {}; | ||
} | ||
} // namespace ProjectionUtilities |
Oops, something went wrong.