From 289d3ec6cd575da01d263f9ea871a2cc3eabde42 Mon Sep 17 00:00:00 2001 From: Jose Alonso Solis-Lemus Date: Tue, 13 Jun 2023 16:57:04 +0100 Subject: [PATCH] Advanced user controls scar --- .../cmdapps/CemrgAppCmdTemplate.cpp | 4 +- .../cmdapps/CemrgAreaFromThreshold.cpp | 4 +- .../cmdapps/CemrgClippingTool.cpp | 6 +- .../cmdapps/CemrgColourSurface.cpp | 2 +- .../cmdapps/CemrgFixShellApp.cpp | 6 +- .../CemrgAppModule/cmdapps/CemrgIM2INR.cpp | 4 +- .../cmdapps/CemrgImageConvertFormat.cpp | 4 +- .../cmdapps/CemrgMorphAnalysis.cpp | 2 +- .../cmdapps/CemrgProjectLgeToVtkMesh.cpp | 6 +- .../cmdapps/CemrgProjectionOptions.cpp | 24 +++- .../cmdapps/CemrgResampleReorient.cpp | 4 +- .../cmdapps/CemrgSimpleRegistration.cpp | 4 +- .../cmdapps/CemrgVentricleSegmRelabel.cpp | 6 +- .../CemrgAppModule/include/CemrgCommonUtils.h | 4 +- .../CemrgAppModule/include/CemrgScar3D.h | 23 ++-- .../CemrgAppModule/src/CemrgCommonUtils.cpp | 20 ++++ .../CemrgAppModule/src/CemrgScar3D.cpp | 103 ++++++++++-------- .../src/internal/AtrialScarView.cpp | 25 ++++- .../src/internal/AtrialScarViewUIScar.ui | 58 ++++++++-- .../src/internal/AtrialScarViewUIcemrgnet.ui | 34 +++++- 20 files changed, 238 insertions(+), 105 deletions(-) diff --git a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgAppCmdTemplate.cpp b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgAppCmdTemplate.cpp index f99c53f9..31267926 100644 --- a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgAppCmdTemplate.cpp +++ b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgAppCmdTemplate.cpp @@ -52,11 +52,11 @@ int main(int argc, char* argv[]) { // Add arguments. Unless specified otherwise, each argument is optional. // See mitkCommandLineParser::addArgument() for more information. parser.addArgument( - "input", "i", mitkCommandLineParser::InputFile, + "input", "i", mitkCommandLineParser::String, "Input Image", "Any image format known to MITK.", us::Any(), false); parser.addArgument( - "output", "o", mitkCommandLineParser::OutputFile, + "output", "o", mitkCommandLineParser::String, "Output file", "Where to save the output.", us::Any(), false); parser.addArgument( diff --git a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgAreaFromThreshold.cpp b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgAreaFromThreshold.cpp index c5e60a48..24871850 100644 --- a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgAreaFromThreshold.cpp +++ b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgAreaFromThreshold.cpp @@ -90,11 +90,11 @@ int main(int argc, char* argv[]) { // Add arguments. Unless specified otherwise, each argument is optional. // See mitkCommandLineParser::addArgument() for more information. // parser.addArgument( - // "input-path", "p", mitkCommandLineParser::InputFile, + // "input-path", "p", mitkCommandLineParser::String, // "Input Directory Path", "Path of directory containing LGE files.", // us::Any(), false); parser.addArgument( - "input", "i", mitkCommandLineParser::InputFile, + "input", "i", mitkCommandLineParser::String, "Surface mesh path", "Full path of mesh vtk polydata file.", us::Any(), false); parser.addArgument( diff --git a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgClippingTool.cpp b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgClippingTool.cpp index 5c459bdb..41412efc 100644 --- a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgClippingTool.cpp +++ b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgClippingTool.cpp @@ -92,15 +92,15 @@ int main(int argc, char* argv[]) { // Add arguments. Unless specified otherwise, each argument is optional. // See mitkCommandLineParser::addArgument() for more information. // parser.addArgument( - // "input-path", "p", mitkCommandLineParser::InputFile, + // "input-path", "p", mitkCommandLineParser::String, // "Input Directory Path", "Path of directory containing LGE files.", // us::Any(), false); parser.addArgument( - "input-vtk", "i", mitkCommandLineParser::InputFile, + "input-vtk", "i", mitkCommandLineParser::String, "segmentation (vtk) path", "Full path of segmentation.vtk file.", us::Any(), false); parser.addArgument( - "output", "o", mitkCommandLineParser::OutputFile, + "output", "o", mitkCommandLineParser::String, "Output file", "Where to save the output.", us::Any(), false); parser.addArgument( diff --git a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgColourSurface.cpp b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgColourSurface.cpp index a6e08e38..4e293d7c 100644 --- a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgColourSurface.cpp +++ b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgColourSurface.cpp @@ -112,7 +112,7 @@ int main(int argc, char* argv[]) { // Add arguments. Unless specified otherwise, each argument is optional. // See mitkCommandLineParser::addArgument() for more information. parser.addArgument("input-segmentation", "i", - mitkCommandLineParser::InputFile,"Input segmentation (.nii)", + mitkCommandLineParser::String,"Input segmentation (.nii)", "Input segmentation file (commonly output of CEMRGNET)", us::Any(), false ); diff --git a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgFixShellApp.cpp b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgFixShellApp.cpp index 0373ac40..e147d4d6 100644 --- a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgFixShellApp.cpp +++ b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgFixShellApp.cpp @@ -85,15 +85,15 @@ int main(int argc, char* argv[]) { // Add arguments. Unless specified otherwise, each argument is optional. // See mitkCommandLineParser::addArgument() for more information. // parser.addArgument( - // "input-path", "p", mitkCommandLineParser::InputFile, + // "input-path", "p", mitkCommandLineParser::String, // "Input Directory Path", "Path of directory containing LGE files.", // us::Any(), false); parser.addArgument( - "input-lge", "i", mitkCommandLineParser::InputFile, + "input-lge", "i", mitkCommandLineParser::String, "LGE path", "Full path of LGE.nii file.", us::Any(), false); parser.addArgument( - "output", "o", mitkCommandLineParser::OutputFile, + "output", "o", mitkCommandLineParser::String, "Output file", "Where to save the output.", us::Any(), false); parser.addArgument( // optional diff --git a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgIM2INR.cpp b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgIM2INR.cpp index c2e802dc..00374a19 100644 --- a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgIM2INR.cpp +++ b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgIM2INR.cpp @@ -92,11 +92,11 @@ int main(int argc, char* argv[]) { // Add arguments. Unless specified otherwise, each argument is optional. // See mitkCommandLineParser::addArgument() for more information. // parser.addArgument( - // "input-path", "p", mitkCommandLineParser::InputFile, + // "input-path", "p", mitkCommandLineParser::String, // "Input Directory Path", "Path of directory containing LGE files.", // us::Any(), false); parser.addArgument( - "input", "i", mitkCommandLineParser::InputFile, + "input", "i", mitkCommandLineParser::String, "Input image", "Full path of image file.", us::Any(), false); parser.addArgument( diff --git a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgImageConvertFormat.cpp b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgImageConvertFormat.cpp index c9b43b46..5d60415a 100644 --- a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgImageConvertFormat.cpp +++ b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgImageConvertFormat.cpp @@ -92,11 +92,11 @@ int main(int argc, char* argv[]) { // Add arguments. Unless specified otherwise, each argument is optional. // See mitkCommandLineParser::addArgument() for more information. // parser.addArgument( - // "input-path", "p", mitkCommandLineParser::InputFile, + // "input-path", "p", mitkCommandLineParser::String, // "Input Directory Path", "Path of directory containing LGE files.", // us::Any(), false); parser.addArgument( - "input", "i", mitkCommandLineParser::InputFile, + "input", "i", mitkCommandLineParser::String, "Input image", "Full path of image file.", us::Any(), false); parser.addArgument( diff --git a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgMorphAnalysis.cpp b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgMorphAnalysis.cpp index 67f5670b..7efe28be 100644 --- a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgMorphAnalysis.cpp +++ b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgMorphAnalysis.cpp @@ -57,7 +57,7 @@ int main(int argc, char* argv[]) { // Add arguments. Unless specified otherwise, each argument is optional. parser.addArgument( - "directory", "d", mitkCommandLineParser::InputFile, + "directory", "d", mitkCommandLineParser::String, "Directory path", "Full path of directory", us::Any(), false); diff --git a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgProjectLgeToVtkMesh.cpp b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgProjectLgeToVtkMesh.cpp index 1a407dd7..3e0cd80f 100644 --- a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgProjectLgeToVtkMesh.cpp +++ b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgProjectLgeToVtkMesh.cpp @@ -93,15 +93,15 @@ int main(int argc, char* argv[]) { // Add arguments. Unless specified otherwise, each argument is optional. // See mitkCommandLineParser::addArgument() for more information. parser.addArgument( - "input-lge", "lge", mitkCommandLineParser::InputFile, + "input-lge", "lge", mitkCommandLineParser::String, "LGE Image", "Full path to the .nii file with the lge score.", us::Any(), false); parser.addArgument( - "input-surface", "surf", mitkCommandLineParser::InputFile, + "input-surface", "surf", mitkCommandLineParser::String, "Surface Image", "Full path to the .vtk file with the surface.", us::Any(), false); parser.addArgument( - "output", "o", mitkCommandLineParser::OutputFile, + "output", "o", mitkCommandLineParser::String, "Output file", "Where to save the output.", us::Any(), false); parser.addArgument( diff --git a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgProjectionOptions.cpp b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgProjectionOptions.cpp index 12ed8a01..abc3b863 100644 --- a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgProjectionOptions.cpp +++ b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgProjectionOptions.cpp @@ -85,11 +85,11 @@ int main(int argc, char* argv[]) { // Add arguments. Unless specified otherwise, each argument is optional. // See mitkCommandLineParser::addArgument() for more information. // parser.addArgument( - // "input-path", "p", mitkCommandLineParser::InputFile, + // "input-path", "p", mitkCommandLineParser::String, // "Input Directory Path", "Path of directory containing LGE files.", // us::Any(), false); parser.addArgument( - "input-lge", "i", mitkCommandLineParser::InputFile, + "input-lge", "i", mitkCommandLineParser::String, "LGE path", "Full path of LGE.nii file.", us::Any(), false); parser.addArgument( // optional @@ -101,6 +101,12 @@ int main(int argc, char* argv[]) { parser.addArgument( // optional "multi-thresholds", "t", mitkCommandLineParser::Bool, "Multiple thresholds", "Produce the output for the scar score using multiple thresholds:\n\t (mean+V*stdev) V = 1:0.1:5\n\t (V*IIR) V = 0.7:0.01:1.61"); + parser.addArgument( // optional + "roi-radius", "radius", mitkCommandLineParser::Bool, + "ROI Radius ON", "Whether to create ROI radius"); + parser.addArgument( // optional + "legacy-projection", "old", mitkCommandLineParser::Bool, + "Legacy (old) projection algorithm", "Legacy (old) projection algorithm"); parser.addArgument( // optional "verbose", "v", mitkCommandLineParser::Bool, "Verbose Output", "Whether to produce verbose output"); @@ -127,6 +133,8 @@ int main(int argc, char* argv[]) { auto thresmethod = 2; auto singlevoxelprojection = false; auto multithreshold = false; + auto roi_radius = false; + auto legacy_projection = false; auto verbose = false; // Parse, cast and set optional argument @@ -146,6 +154,16 @@ int main(int argc, char* argv[]) { } std::cout << "single voxel " << singlevoxelprojection << '\n'; + if (parsedArgs.end() != parsedArgs.find("roi-radius")) { + roi_radius = us::any_cast(parsedArgs["roi-radius"]); + } + + if (parsedArgs.end() != parsedArgs.find("legacy-projection")) { + legacy_projection = us::any_cast(parsedArgs["legacy-projection"]); + } + + roi_radius = roi_radius && !legacy_projection; + if (parsedArgs.end() != parsedArgs.find("verbose")) { verbose = us::any_cast(parsedArgs["verbose"]); } @@ -195,6 +213,8 @@ int main(int argc, char* argv[]) { scar->SetMinStep(minStep); scar->SetMaxStep(maxStep); scar->SetMethodType(methodType); + scar->SetRoiLegacyNormals(legacy_projection); + scar->SetRoiRadiusOption(roi_radius); MITK_INFO(singlevoxelprojection) << "Setting Single voxel projection"; MITK_INFO(!singlevoxelprojection) << "Setting multiple voxels projection"; diff --git a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgResampleReorient.cpp b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgResampleReorient.cpp index 44c818d2..058fb339 100644 --- a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgResampleReorient.cpp +++ b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgResampleReorient.cpp @@ -84,11 +84,11 @@ int main(int argc, char* argv[]) { // Add arguments. Unless specified otherwise, each argument is optional. parser.addArgument( - "input", "i", mitkCommandLineParser::InputFile, + "input", "i", mitkCommandLineParser::String, "NIFTI file path", "Full path of .nii file.", us::Any(), false); parser.addArgument( - "output", "o", mitkCommandLineParser::OutputFile, + "output", "o", mitkCommandLineParser::String, "Output file", "Where to save the output.", us::Any(), false); parser.addArgument( // optional diff --git a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgSimpleRegistration.cpp b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgSimpleRegistration.cpp index 0dc7817c..dfc52a46 100644 --- a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgSimpleRegistration.cpp +++ b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgSimpleRegistration.cpp @@ -54,11 +54,11 @@ int main(int argc, char* argv[]) { // Add arguments. Unless specified otherwise, each argument is optional. // See mitkCommandLineParser::addArgument() for more information. parser.addArgument( - "reference", "i", mitkCommandLineParser::InputFile, + "reference", "i", mitkCommandLineParser::String, "Input object (reference)", "Reference for registration. Accepts any image format known to MITK.", us::Any(), false); parser.addArgument( - "otherimage", "j", mitkCommandLineParser::InputFile, + "otherimage", "j", mitkCommandLineParser::String, "Input object (reference)", "Image to calculate transformation from. Accepts any image format known to MITK.", us::Any(), false); parser.addArgument( // optional diff --git a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgVentricleSegmRelabel.cpp b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgVentricleSegmRelabel.cpp index 25b04288..7c3c3e77 100644 --- a/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgVentricleSegmRelabel.cpp +++ b/CemrgApp/Modules/CemrgAppModule/cmdapps/CemrgVentricleSegmRelabel.cpp @@ -111,15 +111,15 @@ int main(int argc, char* argv[]) { // Add arguments. Unless specified otherwise, each argument is optional. // See mitkCommandLineParser::addArgument() for more information. // parser.addArgument( - // "input-path", "p", mitkCommandLineParser::InputFile, + // "input-path", "p", mitkCommandLineParser::String, // "Input Directory Path", "Path of directory containing LGE files.", // us::Any(), false); parser.addArgument( - "input", "i", mitkCommandLineParser::InputFile, + "input", "i", mitkCommandLineParser::String, "Input image segmentation", "Full path of segmentation file.", us::Any(), false); parser.addArgument( - "bloodpool", "b", mitkCommandLineParser::InputFile, + "bloodpool", "b", mitkCommandLineParser::String, "Input image bloodpool seg", "Full path of bloodpool file.", us::Any(), false); parser.addArgument( // optional diff --git a/CemrgApp/Modules/CemrgAppModule/include/CemrgCommonUtils.h b/CemrgApp/Modules/CemrgAppModule/include/CemrgCommonUtils.h index 9ba18ab3..b654d69f 100644 --- a/CemrgApp/Modules/CemrgAppModule/include/CemrgCommonUtils.h +++ b/CemrgApp/Modules/CemrgAppModule/include/CemrgCommonUtils.h @@ -57,9 +57,11 @@ class MITKCEMRGAPPMODULE_EXPORT CemrgCommonUtils { // Image Analysis Utils static void SetSegmentationEdgesToZero(mitk::Image::Pointer image, QString outPath=""); - static void Binarise(mitk::Image::Pointer image, float background=0); static mitk::Image::Pointer ReturnBinarised(mitk::Image::Pointer image, float background=0); + static void Binarise(mitk::Image::Pointer image, float background=0); + static mitk::Image::Pointer Zeros(mitk::Image::Pointer image); + //Nifti Conversion Utils static bool ConvertToNifti(mitk::BaseData::Pointer oneNode, QString path2file, bool resample=false, bool reorient=false); static void RoundPixelValues(QString pathToImage, QString outputPath=""); diff --git a/CemrgApp/Modules/CemrgAppModule/include/CemrgScar3D.h b/CemrgApp/Modules/CemrgAppModule/include/CemrgScar3D.h index 9231f567..37d20041 100644 --- a/CemrgApp/Modules/CemrgAppModule/include/CemrgScar3D.h +++ b/CemrgApp/Modules/CemrgAppModule/include/CemrgScar3D.h @@ -36,10 +36,12 @@ PURPOSE. See the above copyright notices for more information. #include #include #include +#include class MITKCEMRGAPPMODULE_EXPORT CemrgScar3D { public: + enum DebugImageType { BACKGROUND=0, CORRIDOR, PROJECTED }; CemrgScar3D(); mitk::Surface::Pointer Scar3D(std::string directory, mitk::Image::Pointer lgeImage, std::string segname = "segmentation.vtk"); @@ -52,29 +54,28 @@ class MITKCEMRGAPPMODULE_EXPORT CemrgScar3D { void PrintThresholdingResults(QString dir, std::vector values_vector, int threshType, double mean, double stdv, bool printGuide = true); void PrintSingleThresholdingResult(QString dir, double value, int threshType, double mean, double stdv); - double GetMinScalar() const; - double GetMaxScalar() const; - void SetMinStep(int value); - void SetMaxStep(int value); - void SetMethodType(int value); + inline double GetMinScalar() const { return minScalar; }; + inline double GetMaxScalar() const { return maxScalar; }; + inline void SetMinStep(int value) { minStep = value; }; + inline void SetMaxStep(int value) { maxStep = value; }; + inline void SetMethodType(int value) { methodType = value; }; void SetScarSegImage(const mitk::Image::Pointer image); - void SetVoxelBasedProjection(bool value); - inline void SetDebug(bool b){debugging=b;}; - inline void SetDebugOn(){SetDebug(true);}; - inline void SetDebugOff(){SetDebug(false);}; + inline void SetVoxelBasedProjection(bool value){voxelBasedProjection=value;}; + inline void SetRoiLegacyNormals(bool value){roiLegacyNormals=value;}; + inline void SetRoiRadiusOption(bool value){roiRadiusOption=value;}; private: int methodType; int minStep, maxStep; - bool voxelBasedProjection, debugging; + bool voxelBasedProjection, roiLegacyNormals, roiRadiusOption; double minScalar, maxScalar; vtkSmartPointer scalars; typedef itk::Image itkImageType; itkImageType::Pointer scarSegImage; - itk::Image::Pointer scarDebugLabel; + itk::Image::Pointer scarDebugCorridor; double GetIntensityAlongNormal( itkImageType::Pointer scarImage, itkImageType::Pointer visitedImage, diff --git a/CemrgApp/Modules/CemrgAppModule/src/CemrgCommonUtils.cpp b/CemrgApp/Modules/CemrgAppModule/src/CemrgCommonUtils.cpp index ab503a19..e2d26d5c 100644 --- a/CemrgApp/Modules/CemrgAppModule/src/CemrgCommonUtils.cpp +++ b/CemrgApp/Modules/CemrgAppModule/src/CemrgCommonUtils.cpp @@ -436,6 +436,26 @@ void CemrgCommonUtils::SetSegmentationEdgesToZero(mitk::Image::Pointer image, QS } } + mitk::Image::Pointer CemrgCommonUtils::Zeros(mitk::Image::Pointer image){ + using ImageType = itk::Image; + + ImageType::Pointer outputImg = ImageType::New(); + mitk::CastToItkImage(image->Clone(), outputImg); + + using IteratorType = itk::ImageRegionIterator; + IteratorType imIter(outputImg, outputImg->GetLargestPossibleRegion()); + imIter.GoToBegin(); + while(!imIter.IsAtEnd()){ + imIter.Set(0); + ++imIter; + } + + mitk::Image::Pointer outim = mitk::Image::New(); + mitk::CastToMitkImage(outputImg, outim); + + return outim; + } + void CemrgCommonUtils::RoundPixelValues(QString pathToImage, QString outputPath) { QFileInfo fi(pathToImage); if (fi.exists()) { diff --git a/CemrgApp/Modules/CemrgAppModule/src/CemrgScar3D.cpp b/CemrgApp/Modules/CemrgAppModule/src/CemrgScar3D.cpp index d901ca5e..5b3bd4f6 100644 --- a/CemrgApp/Modules/CemrgAppModule/src/CemrgScar3D.cpp +++ b/CemrgApp/Modules/CemrgAppModule/src/CemrgScar3D.cpp @@ -57,6 +57,7 @@ PURPOSE. See the above copyright notices for more information. // Qt #include #include +#include // C++ Standard #include @@ -71,8 +72,10 @@ CemrgScar3D::CemrgScar3D() { this->minStep = -3, this->maxStep = 3; this->minScalar = 1E10, this->maxScalar = -1; this->voxelBasedProjection = false; - this->debugging = false; this->scalars = vtkSmartPointer::New(); + + this->roiLegacyNormals = false; + this->roiRadiusOption = true; } mitk::Surface::Pointer CemrgScar3D::Scar3D(std::string directory, mitk::Image::Pointer lgeImage, std::string segname) { @@ -83,6 +86,16 @@ mitk::Surface::Pointer CemrgScar3D::Scar3D(std::string directory, mitk::Image::P itkImageType::Pointer visitedImage = itkImageType::New(); ItkDeepCopy(scarImage, visitedImage); + mitk::Image::Pointer corridor_im = CemrgCommonUtils::Zeros(lgeImage); + mitk::CastToItkImage(corridor_im, scarDebugCorridor); + typedef itk::ImageRegionIterator ImIteratorType; + ImIteratorType corrIt(scarDebugCorridor, scarDebugCorridor->GetLargestPossibleRegion()); + + for (corrIt.GoToBegin(); !corrIt.IsAtEnd(); ++corrIt) { + corrIt.Set(DebugImageType::BACKGROUND); + } + + //Read in the mesh std::string path = directory + "/" + segname; mitk::Surface::Pointer surface = CemrgCommonUtils::LoadVTKMesh(path); @@ -149,14 +162,16 @@ mitk::Surface::Pointer CemrgScar3D::Scar3D(std::string directory, mitk::Image::P cY /= numPoints; cZ /= numPoints; - // ITK method - pointXYZ[0] = pN[0]; - pointXYZ[1] = pN[1]; - pointXYZ[2] = pN[2]; - scarImage->TransformPhysicalPointToIndex(pointXYZ, pixelXYZ); - pN[0] = pixelXYZ[0]; - pN[1] = pixelXYZ[1]; - pN[2] = pixelXYZ[2]; + if (roiLegacyNormals) { + // ITK method + pointXYZ[0] = pN[0]; + pointXYZ[1] = pN[1]; + pointXYZ[2] = pN[2]; + scarImage->TransformPhysicalPointToIndex(pointXYZ, pixelXYZ); + pN[0] = pixelXYZ[0]; + pN[1] = pixelXYZ[1]; + pN[2] = pixelXYZ[2]; + } double scalar = GetIntensityAlongNormal(scarImage, visitedImage, pN[0], pN[1], pN[2], cX, cY, cZ); @@ -211,7 +226,6 @@ mitk::Surface::Pointer CemrgScar3D::Scar3D(std::string directory, mitk::Image::P // allScalarsInShell.push_back(scalar); } }//_for - scarDebugLabel = visitedImage; pd->GetCellData()->SetScalars(scalars); surface->SetVtkPolyData(pd); return surface; @@ -395,31 +409,6 @@ void CemrgScar3D::PrintSingleThresholdingResult(QString dir, double value, int t PrintThresholdingResults(dir, v, threshType, mean, stdv, true); } -double CemrgScar3D::GetMinScalar() const { - - return minScalar; -} - -double CemrgScar3D::GetMaxScalar() const { - - return maxScalar; -} - -void CemrgScar3D::SetMinStep(int value) { - - minStep = value; -} - -void CemrgScar3D::SetMaxStep(int value) { - - maxStep = value; -} - -void CemrgScar3D::SetMethodType(int value) { - - methodType = value; -} - void CemrgScar3D::SetScarSegImage(const mitk::Image::Pointer image) { //Setup roiImage @@ -428,11 +417,6 @@ void CemrgScar3D::SetScarSegImage(const mitk::Image::Pointer image) { this->scarSegImage = itkImage; } -void CemrgScar3D::SetVoxelBasedProjection(bool value) { - - voxelBasedProjection = value; -} - double CemrgScar3D::GetIntensityAlongNormal(itkImageType::Pointer scarImage, itkImageType::Pointer visitedImage, double n_x, double n_y, double n_z, double centre_x, double centre_y, double centre_z) { @@ -458,20 +442,41 @@ double CemrgScar3D::GetIntensityAlongNormal(itkImageType::Pointer scarImage, itk int maxY = sizeOfImage[1]; int maxZ = sizeOfImage[2]; + int roi_lim = roiRadiusOption ? 1 : 0; + + QStringList debug_vals; + int count = 1; + for (double i = scar_step_min; i <= scar_step_max; i += scar_step_size) { double x = floor(centre_x + (i * n_x)); double y = floor(centre_y + (i * n_y)); double z = floor(centre_z + (i * n_z)); - for (int a = -1; a <= 1; a++) { - for (int b = -1; b <= 1; b++) { - for (int c = -1; c <= 1; c++) { + for (int a = -roi_lim; a <= roi_lim; a++) { + for (int b = -roi_lim; b <= roi_lim; b++) { + for (int c = -roi_lim; c <= roi_lim; c++) { if (x + a >= 0 && x + a < maxX && y + b >= 0 && y + b < maxY && z + c >= 0 && z + c < maxZ) { mitk::Point3D tempPoint; - tempPoint.SetElement(0, x + a); - tempPoint.SetElement(1, y + b); - tempPoint.SetElement(2, z + c); + itkImageType::IndexType pixel_xyz; + pixel_xyz[0] = x + a; + pixel_xyz[1] = y + b; + pixel_xyz[2] = z + c; + + tempPoint.SetElement(0, pixel_xyz[0]); + tempPoint.SetElement(1, pixel_xyz[1]); + tempPoint.SetElement(2, pixel_xyz[2]); pointsOnAndAroundNormal.push_back(tempPoint); + scarDebugCorridor->SetPixel(pixel_xyz, DebugImageType::CORRIDOR); + + //debug save in list pixel location on image + debug_vals << QString::number(count) << ", "; + debug_vals << QString::number(i) << ", "; + debug_vals << QString::number(x + a) << ", "; + debug_vals << QString::number(y + b) << ", "; + debug_vals << QString::number(z + c) << "\n"; + + count++; + } } } @@ -551,6 +556,7 @@ double CemrgScar3D::GetStatisticalMeasure(std::vector pointsOnAnd pixel_xyz[1] = pointsOnAndAroundNormal.at(maxIndex).GetElement(1); pixel_xyz[2] = pointsOnAndAroundNormal.at(maxIndex).GetElement(2); visitedImage->SetPixel(pixel_xyz, 1); + scarDebugCorridor->SetPixel(pixel_xyz, DebugImageType::PROJECTED); } }//_if_max @@ -627,6 +633,9 @@ void CemrgScar3D::ItkDeepCopy(itkImageType::Pointer input, itkImageType::Pointer ++inputIterator; ++outputIterator; } + + output->SetOrigin(input->GetOrigin()); + output->SetSpacing(input->GetSpacing()); } void CemrgScar3D::SaveScarDebugImage(QString name, QString dir) { @@ -640,6 +649,6 @@ void CemrgScar3D::SaveScarDebugImage(QString name, QString dir) { WriterType::Pointer writer = WriterType::New(); writer->SetFileName(debugSCARname.toStdString()); - writer->SetInput(this->scarDebugLabel); + writer->SetInput(this->scarDebugCorridor); writer->Update(); } diff --git a/CemrgApp/Plugins/kcl.cemrgapp.scar/src/internal/AtrialScarView.cpp b/CemrgApp/Plugins/kcl.cemrgapp.scar/src/internal/AtrialScarView.cpp index 6a63c531..6442b2ad 100644 --- a/CemrgApp/Plugins/kcl.cemrgapp.scar/src/internal/AtrialScarView.cpp +++ b/CemrgApp/Plugins/kcl.cemrgapp.scar/src/internal/AtrialScarView.cpp @@ -1431,11 +1431,14 @@ void AtrialScarView::ScarMap() { if (dialogCode == QDialog::Accepted) { bool ok1, ok2; - int minStep = m_UIScar.lineEdit_1->text().toInt(&ok1); - int maxStep = m_UIScar.lineEdit_2->text().toInt(&ok2); + int minStep = m_UIScar.line_roi_minStep->text().toInt(&ok1); + int maxStep = m_UIScar.line_roi_maxStep->text().toInt(&ok2); int methodType = m_UIScar.radioButton_1->isChecked() ? 2 : 1; QString meType = m_UIScar.radioButton_1->isChecked() ? "Max" : "Mean"; - bool voxelBasedProjection = m_UIScar.checkBox->isChecked(); + + bool voxelBasedProjection = m_UIScar.check_roi_voxelBased->isChecked(); + bool UseRoiLegacyNormals = m_UIScar.check_roi_legacyNormals->isChecked(); + bool UseRoiRadius = m_UIScar.check_roi_radius->isChecked(); //Set default values if (!ok1 || !ok2) @@ -1444,6 +1447,19 @@ void AtrialScarView::ScarMap() { if (!ok2) maxStep = 3; //_if + std::string msg; + if (UseRoiLegacyNormals){ + msg = "Using an old version of the normals algorithm. Setting ROI radius option to ON."; + UseRoiRadius = true; + QMessageBox::warning(NULL, "Attention", msg.c_str()); + MITK_WARN << msg; + } + + if (!UseRoiRadius){ + msg = "The volume of the projection ROI is reduced and might cause a problem with scar calculation."; + QMessageBox::warning(NULL, " Attention ", msg.c_str()); + MITK_WARN << msg; + } /* * Producibility Test **/ @@ -1465,6 +1481,9 @@ void AtrialScarView::ScarMap() { scar->SetMaxStep(maxStep); scar->SetMethodType(methodType); scar->SetVoxelBasedProjection(voxelBasedProjection); + scar->SetRoiLegacyNormals(UseRoiLegacyNormals); + scar->SetRoiRadiusOption(UseRoiRadius); + mitk::Image::Pointer scarSegImg; try { QString path = directory + "/" + fileName; diff --git a/CemrgApp/Plugins/kcl.cemrgapp.scar/src/internal/AtrialScarViewUIScar.ui b/CemrgApp/Plugins/kcl.cemrgapp.scar/src/internal/AtrialScarViewUIScar.ui index cee7e862..498e81ad 100644 --- a/CemrgApp/Plugins/kcl.cemrgapp.scar/src/internal/AtrialScarViewUIScar.ui +++ b/CemrgApp/Plugins/kcl.cemrgapp.scar/src/internal/AtrialScarViewUIScar.ui @@ -6,8 +6,8 @@ 0 0 - 223 - 239 + 257 + 341 @@ -25,7 +25,7 @@ 16777215 - 239 + 512 @@ -70,7 +70,20 @@ - + + + QLabel { color: rgb(255, 0, 0) } + + + Projection ROI Parameters + + + Qt::AlignCenter + + + + + @@ -80,26 +93,49 @@ - + Max Step (default = 3) - - - Qt::Horizontal + + + <html><head/><body><p>Changes the intensity's projection method. Resulting in unsmoothed and less fibrotic regions.</p></body></html> + + + Voxel Based Projection - + - <html><head/><body><p>Changes the intensity's projection method. Resulting in unsmoothed and less fibrotic regions.</p></body></html> + <html><body><p>Use or not the standard region of interest radius. Default is ON</p></body></html> - Voxel Based Projection + ROI Radius + + + true + + + + + + + <html><body><p>Uses old algorithm to project and calculate scar shell normals.</p></body></html> + + + Legacy Projection Algorithm + + + + + + + Qt::Horizontal diff --git a/CemrgApp/Plugins/kcl.cemrgapp.scar/src/internal/AtrialScarViewUIcemrgnet.ui b/CemrgApp/Plugins/kcl.cemrgapp.scar/src/internal/AtrialScarViewUIcemrgnet.ui index e1ce856a..3cba08ec 100644 --- a/CemrgApp/Plugins/kcl.cemrgapp.scar/src/internal/AtrialScarViewUIcemrgnet.ui +++ b/CemrgApp/Plugins/kcl.cemrgapp.scar/src/internal/AtrialScarViewUIcemrgnet.ui @@ -6,8 +6,8 @@ 0 0 - 480 - 480 + 512 + 512 @@ -18,8 +18,8 @@ - 480 - 480 + 512 + 512 @@ -309,6 +309,32 @@ Voxel-based method + + + + 180 + 220 + 81 + 21 + + + + ROI Radius + + + + + + 280 + 220 + 161 + 21 + + + + Legacy Projection Algorithm + +