diff --git a/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidHeadNeckRegistrationAlgorithm.h b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidHeadNeckRegistrationAlgorithm.h new file mode 100644 index 0000000000..b73c05ab33 --- /dev/null +++ b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidHeadNeckRegistrationAlgorithm.h @@ -0,0 +1,28 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef mitkMultiModalRigidHeadNeckRegistrationAlgorithm_h +#define mitkMultiModalRigidHeadNeckRegistrationAlgorithm_h + +#include "mapDiscreteElements.h" +#include "mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.h" +#include "mapConfigure.h" + +#include "mitkMultiModalRigidHeadNeckRegistrationAlgorithm_ProfileResource.h" + +namespace mitk +{ + template + using MultiModalRigidHeadNeckRegistrationAlgorithm = typename map::algorithm::boxed::MultiModalRigidHeadNeckRegistrationAlgorithm; +} + +#endif \ No newline at end of file diff --git a/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidHeadNeckRegistrationAlgorithm.profile b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidHeadNeckRegistrationAlgorithm.profile new file mode 100644 index 0000000000..eccff83a0d --- /dev/null +++ b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidHeadNeckRegistrationAlgorithm.profile @@ -0,0 +1,20 @@ +SET(ALGORITHM_PROFILE_UID_Namespace "org.mitk") +SET(ALGORITHM_PROFILE_UID_Name "MultiModal.rigid.Head2HeadNeck") +SET(ALGORITHM_PROFILE_UID_Version "1.0.0") + +SET(ALGORITHM_PROFILE_Description "Algorithm is used for special cases where a head image and a head neck image (assumed to be the larger image in z direction) should be registered. It skips the lower part of the head neck image if a preinitialization (via geometric center or centroid) is used, to establish a better initialization. By default initializes via geometric centers.") +SET(ALGORITHM_PROFILE_Contact "Ralf Floca\; mitk-users@lists.sourceforge.net") + +SET(ALGORITHM_PROFILE_DataType "Image") +SET(ALGORITHM_PROFILE_ResolutionStyle "3 (multi res)") +SET(ALGORITHM_PROFILE_DimMoving "3") +SET(ALGORITHM_PROFILE_ModalityMoving "MR" "any") +SET(ALGORITHM_PROFILE_DimTarget "3") +SET(ALGORITHM_PROFILE_ModalityTarget "MR" "any") +SET(ALGORITHM_PROFILE_Subject "any") +SET(ALGORITHM_PROFILE_Object "Head" "Head/Neck") +SET(ALGORITHM_PROFILE_TransformModel "rigid") +SET(ALGORITHM_PROFILE_Metric "Mattes mutual information") +SET(ALGORITHM_PROFILE_TransformDomain "global") +SET(ALGORITHM_PROFILE_Optimization "Regular Step Gradient Descent") +SET(ALGORITHM_PROFILE_Keywords "basic" "pre initialization" "Head/Neck" "HeadNeck" "multimodal" "rigid") diff --git a/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm.h b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm.h new file mode 100644 index 0000000000..925c5484a2 --- /dev/null +++ b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm.h @@ -0,0 +1,28 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm_h +#define mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm_h + +#include "mapDiscreteElements.h" +#include "mapITKRigid3DMattesMISlabbedHeadRegistrationAlgorithmTemplate.h" +#include "mapConfigure.h" + +#include "mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm_ProfileResource.h" + +namespace mitk +{ + template + using MultiModalRigidSlabbedHeadRegistrationAlgorithm = typename map::algorithm::boxed::MultiModalRigidSlabbedHeadRegistrationAlgorithm; +} + +#endif \ No newline at end of file diff --git a/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm.profile b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm.profile new file mode 100644 index 0000000000..4f455fdf68 --- /dev/null +++ b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm.profile @@ -0,0 +1,20 @@ +SET(ALGORITHM_PROFILE_UID_Namespace "org.mitk") +SET(ALGORITHM_PROFILE_UID_Name "MultiModal.rigid.slabbedHead") +SET(ALGORITHM_PROFILE_UID_Version "1.0.0") + +SET(ALGORITHM_PROFILE_Description "Algorithm is used to solve a special case of head registration problems. It is configured to register the slabbed MRI head data (thus data where only a part of the head is visible) onto whole Head images (e.g.CT planning data). Differenz to the default rigid algorithm is that this algorithms is very defensive with rotating out of the slice plan (so roll or pitch). Uses 3 Resolution levels. By default initializes via image centers.") +SET(ALGORITHM_PROFILE_Contact "Ralf Floca\; mitk-users@lists.sourceforge.net") + +SET(ALGORITHM_PROFILE_DataType "Image") +SET(ALGORITHM_PROFILE_ResolutionStyle "3 (multi res)") +SET(ALGORITHM_PROFILE_DimMoving "3") +SET(ALGORITHM_PROFILE_ModalityMoving "MR" "any") +SET(ALGORITHM_PROFILE_DimTarget "3") +SET(ALGORITHM_PROFILE_ModalityTarget "MR" "any") +SET(ALGORITHM_PROFILE_Subject "any") +SET(ALGORITHM_PROFILE_Object "Head") +SET(ALGORITHM_PROFILE_TransformModel "rigid") +SET(ALGORITHM_PROFILE_Metric "Mattes mutual information") +SET(ALGORITHM_PROFILE_TransformDomain "global") +SET(ALGORITHM_PROFILE_Optimization "Regular Step Gradient Descent") +SET(ALGORITHM_PROFILE_Keywords "basic" "pre initialization" "Head" "slabbed" "partial" "multimodal" "rigid") diff --git a/Modules/MatchPointRegistration/cmdapps/MatchImageMiniApp.cpp b/Modules/MatchPointRegistration/cmdapps/MatchImageMiniApp.cpp index 1292f6d85e..c7d5f0de2c 100644 --- a/Modules/MatchPointRegistration/cmdapps/MatchImageMiniApp.cpp +++ b/Modules/MatchPointRegistration/cmdapps/MatchImageMiniApp.cpp @@ -1,314 +1,314 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include // MatchPoint #include #include #include #include #include #include #include #include #include #include #include std::string movingFileName; std::string targetFileName; std::string outFileName; std::string algFileName; void SetupParser(mitkCommandLineParser& parser) { parser.setTitle("Image Matcher"); parser.setCategory("Registration Tools"); parser.setDescription(""); parser.setContributor("MIC, German Cancer Research Center (DKFZ)"); parser.setArgumentPrefix("--", "-"); // Add command line argument names parser.beginGroup("Required I/O parameters"); parser.addArgument( "moving", "m", mitkCommandLineParser::File, "Moving image files", "Path to the data that should be registred into the target space.", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument( "target", "t", mitkCommandLineParser::File, "Tareget image files", "Path to the data that should be the target data on which the moving data should be registered.", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument( "algorithm", "a", mitkCommandLineParser::File, "Registration algorithm", "Path to the registration algorithm that should be used for registration.", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file path", "Path to the generated registration.", us::Any(), false, false, false, mitkCommandLineParser::Output); parser.endGroup(); parser.beginGroup("Optional parameters"); parser.addArgument("template", "t", mitkCommandLineParser::File, "Output template image.", "File path to an image that serves as template for the output geometry.", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument( "registrations", "r", mitkCommandLineParser::StringList, "Registration files", "Pathes to the registrations that should be used to map the input images. If this parameter is not set, identity transforms are assumed. If this parameter is set, it must have the same number of entries then the parameter inputs. If you want to use and identity transform for a specific input, specify an empty string. The application assumes that inputs and registrations have the same order, so the n-th input should use thr n-th registration.", us::Any(), true, false, false, mitkCommandLineParser::Input); parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); parser.endGroup(); } bool ConfigureApplicationSettings(std::map parsedArgs) { try { if (parsedArgs.size() == 0) return false; movingFileName = us::any_cast(parsedArgs["moving"]); targetFileName = us::any_cast(parsedArgs["target"]); outFileName = us::any_cast(parsedArgs["output"]); algFileName = us::any_cast(parsedArgs["algorithm"]); } catch (...) { return false; } return true; } map::deployment::RegistrationAlgorithmBasePointer loadAlgorithm() { map::deployment::RegistrationAlgorithmBasePointer spAlgorithmBase = nullptr; std::cout << std::endl << "Load registration algorithm..." << std::endl; map::deployment::DLLHandle::Pointer spHandle = nullptr; spHandle = map::deployment::openDeploymentDLL(algFileName); if (spHandle.IsNull()) { mapDefaultExceptionStaticMacro(<< "Cannot open deployed registration algorithm file."); } std::cout << "... libary opened..." << std::endl; std::cout << "Algorithm information: " << std::endl; spHandle->getAlgorithmUID().Print(std::cout, 2); std::cout << std::endl; //Now load the algorthm from DLL spAlgorithmBase = map::deployment::getRegistrationAlgorithm(spHandle); if (spAlgorithmBase.IsNotNull()) { std::cout << "... done" << std::endl << std::endl; } else { mapDefaultExceptionStaticMacro(<< "Cannot create algorithm instance"); } return spAlgorithmBase; }; mitk::Image::Pointer ExtractFirstFrame(const mitk::Image* dynamicImage) { mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); imageTimeSelector->SetInput(dynamicImage); imageTimeSelector->SetTimeNr(0); imageTimeSelector->UpdateLargestPossibleRegion(); return imageTimeSelector->GetOutput(); } void OnMapAlgorithmEvent(::itk::Object*, const itk::EventObject& event, void*) { const map::events::AlgorithmEvent* pAlgEvent = dynamic_cast(&event); const map::events::AlgorithmWrapperEvent* pWrapEvent = dynamic_cast(&event); const map::events::InitializingAlgorithmEvent* pInitEvent = dynamic_cast(&event); const map::events::StartingAlgorithmEvent* pStartEvent = dynamic_cast(&event); const map::events::StoppingAlgorithmEvent* pStoppingEvent = dynamic_cast(&event); const map::events::StoppedAlgorithmEvent* pStoppedEvent = dynamic_cast(&event); const map::events::FinalizingAlgorithmEvent* pFinalizingEvent = dynamic_cast(&event); const map::events::FinalizedAlgorithmEvent* pFinalizedEvent = dynamic_cast(&event); if (pInitEvent) { std::cout <<"Initializing algorithm ..." << std::endl; } else if (pStartEvent) { std::cout <<"Starting algorithm ..." << std::endl; } else if (pStoppingEvent) { std::cout <<"Stopping algorithm ..." << std::endl; } else if (pStoppedEvent) { std::cout <<"Stopped algorithm ..." << std::endl; if (!pStoppedEvent->getComment().empty()) { std::cout <<"Stopping condition: " << pStoppedEvent->getComment() << std::endl; } } else if (pFinalizingEvent) { std::cout <<"Finalizing algorithm and results ..." << std::endl; } else if (pFinalizedEvent) { std::cout <<"Finalized algorithm ..." << std::endl; } else if (pAlgEvent && !pWrapEvent) { std::cout << pAlgEvent->getComment() << std::endl; } } int main(int argc, char* argv[]) { std::cout << "MitkRegistrationMiniApp - Generic light weight image registration tool based on MatchPoint." << std::endl; mitkCommandLineParser parser; SetupParser(parser); const std::map& parsedArgs = parser.parseArguments(argc, argv); if (!ConfigureApplicationSettings(parsedArgs)) { MITK_ERROR << "Command line arguments are invalid. To see the correct usage please call with -h or --help to show the help information."; return EXIT_FAILURE; }; // Show a help message if (parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } std::cout << std::endl << "*******************************************" << std::endl; std::cout << "Moving file: " << movingFileName << std::endl; std::cout << "Target file: " << targetFileName << std::endl; std::cout << "Output file: " << outFileName << std::endl; std::cout << "Algorithm location: " << algFileName << std::endl; //load algorithm try { auto algorithm = loadAlgorithm(); auto command = ::itk::CStyleCommand::New(); command->SetCallback(OnMapAlgorithmEvent); - auto observerID = algorithm->AddObserver(::map::events::AlgorithmEvent(), command); + algorithm->AddObserver(::map::events::AlgorithmEvent(), command); std::cout << "Load moving data..." << std::endl; auto movingImage = mitk::IOUtil::Load(movingFileName); if (movingImage.IsNull()) { MITK_ERROR << "Cannot load moving image."; return EXIT_FAILURE; } if (movingImage->GetTimeSteps() > 1) { movingImage = mitk::SelectImageByTimeStep(movingImage, 0)->Clone(); //we have to clone because SelectImageByTimeStep //only generates as new view of the data and we //are overwriting the only smartpointer to the source. std::cout << "Moving image has multiple time steps. Use first time step for registartion." << std::endl; } std::cout << "Load target data..." << std::endl; auto targetImage = mitk::IOUtil::Load(targetFileName); if (targetImage.IsNull()) { MITK_ERROR << "Cannot load target image."; return EXIT_FAILURE; } if (targetImage->GetTimeSteps() > 1) { targetImage = mitk::SelectImageByTimeStep(targetImage, 0)->Clone(); //we have to clone because SelectImageByTimeStep //only generates as new view of the data and we //are overwriting the only smartpointer to the source. std::cout << "Target image has multiple time steps. Use first time step for registartion." << std::endl; } std::cout << "Start registration...." << std::endl; mitk::MAPAlgorithmHelper helper(algorithm); helper.SetData(movingImage, targetImage); ::itk::StdStreamLogOutput::Pointer spStreamLogOutput = ::itk::StdStreamLogOutput::New(); spStreamLogOutput->SetStream(std::cout); map::core::Logbook::addAdditionalLogOutput(spStreamLogOutput); auto registration = helper.GetRegistration(); // wrap the registration in a data node if (registration.IsNull()) { MITK_ERROR << "No valid registration generated"; return EXIT_FAILURE; } auto regWrapper = mitk::MAPRegistrationWrapper::New(registration); std::cout << "Store registration...." << std::endl; mitk::IOUtil::Save(regWrapper, outFileName); } catch (const std::exception& e) { MITK_ERROR << e.what(); return EXIT_FAILURE; } catch (...) { MITK_ERROR << "Unexpected error encountered."; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/MatchPointRegistration/deployment/CMakeLists.txt b/Modules/MatchPointRegistration/deployment/CMakeLists.txt index 120526bfa0..b0a51b1ce6 100644 --- a/Modules/MatchPointRegistration/deployment/CMakeLists.txt +++ b/Modules/MatchPointRegistration/deployment/CMakeLists.txt @@ -1,8 +1,10 @@ set(MDRA_INCLUDE_DIRS PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../algorithms) mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_MultiModal_affine_default CPP_FILES mitkMultiModalAffine_default.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS}) mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_MultiModal_rigid_default CPP_FILES mitkMultiModalRigid_default.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS}) +mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_MultiModal_rigid_headNeck CPP_FILES mitkMultiModalRigid_headNeck.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS}) +mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_MultiModal_rigid_slabbedHead CPP_FILES mitkMultiModalRigid_slabbedHead.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS}) mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_MultiModal_translation_default CPP_FILES mitkMultiModalTrans_default.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS}) mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_Rigid_closedform_points_default CPP_FILES mitkRigidClosedFormPoints_default.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS}) mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_Rigid_ICP_default CPP_FILES mitkRigidICP_default.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS}) mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_FastSymmetricForcesDemons_MultiRes_default CPP_FILES mitkFastSymmetricForcesDemonsMultiRes_default.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS}) mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_LevelSetMotion_MultiRes_default CPP_FILES mitkLevelSetMotionMultiRes_default.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS}) diff --git a/Modules/MatchPointRegistration/deployment/mitkMultiModalRigid_headNeck.cpp b/Modules/MatchPointRegistration/deployment/mitkMultiModalRigid_headNeck.cpp new file mode 100644 index 0000000000..86791c6458 --- /dev/null +++ b/Modules/MatchPointRegistration/deployment/mitkMultiModalRigid_headNeck.cpp @@ -0,0 +1,21 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include "mapDeploymentDLLHelper.h" +#include "mapDiscreteElements.h" +#include "mapConfigure.h" + +#include "mitkMultiModalRigidHeadNeckRegistrationAlgorithm.h" + +typedef map::core::discrete::Elements<3>::InternalImageType ImageType; + +mapDeployAlgorithmMacro(mitk::MultiModalRigidHeadNeckRegistrationAlgorithm); diff --git a/Modules/MatchPointRegistration/deployment/mitkMultiModalRigid_slabbedHead.cpp b/Modules/MatchPointRegistration/deployment/mitkMultiModalRigid_slabbedHead.cpp new file mode 100644 index 0000000000..eaee90756c --- /dev/null +++ b/Modules/MatchPointRegistration/deployment/mitkMultiModalRigid_slabbedHead.cpp @@ -0,0 +1,21 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include "mapDeploymentDLLHelper.h" +#include "mapDiscreteElements.h" +#include "mapConfigure.h" + +#include "mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm.h" + +typedef map::core::discrete::Elements<3>::InternalImageType ImageType; + +mapDeployAlgorithmMacro(mitk::MultiModalRigidSlabbedHeadRegistrationAlgorithm);