diff --git a/Modules/MatchPointRegistration/CMakeLists.txt b/Modules/MatchPointRegistration/CMakeLists.txt index fc7b8603c5..acbcd26ff3 100644 --- a/Modules/MatchPointRegistration/CMakeLists.txt +++ b/Modules/MatchPointRegistration/CMakeLists.txt @@ -1,27 +1,28 @@ MITK_CREATE_MODULE( INCLUDE_DIRS PUBLIC algorithms PRIVATE src/Helper src/Rendering DEPENDS MitkCore MitkSceneSerializationBase PACKAGE_DEPENDS PUBLIC MatchPoint ) if(TARGET ${MODULE_TARGET}) set(ALG_PROFILE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/algorithms) include(${MatchPoint_SOURCE_DIR}/CMake/mapFunctionCreateAlgorithmProfile.cmake) file(GLOB ALG_PROFILE_FILES LIST_DIRECTORIES false RELATIVE ${ALG_PROFILE_DIR} "${ALG_PROFILE_DIR}/*.profile") foreach(profile_file ${ALG_PROFILE_FILES}) get_filename_component(profile_name ${profile_file} NAME_WE) MESSAGE(STATUS "... generate MDRA profile ${profile_name} (from ${profile_file})...") CREATE_ALGORITHM_PROFILE(${profile_name} ${ALG_PROFILE_DIR}/${profile_file}) endforeach(profile_file) ADD_SUBDIRECTORY(autoload/IO) ADD_SUBDIRECTORY(deployment) if(BUILD_TESTING) ADD_SUBDIRECTORY(Testing) endif(BUILD_TESTING) + ADD_SUBDIRECTORY(cmdapps) endif() diff --git a/Modules/MatchPointRegistration/cmdapps/CMakeLists.txt b/Modules/MatchPointRegistration/cmdapps/CMakeLists.txt new file mode 100644 index 0000000000..f02ab70bc2 --- /dev/null +++ b/Modules/MatchPointRegistration/cmdapps/CMakeLists.txt @@ -0,0 +1,33 @@ +option(BUILD_MatchPointCmdApps "Build commandline tools for the MatchPoint module" OFF) + +if(BUILD_MatchPointCmdApps OR MITK_BUILD_ALL_APPS) + + # needed include directories + include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ) + # list of CmdApps + # if an app requires additional dependencies + # they are added after a "^^" and separated by "_" + set( cmdapps + StitchImagesMiniApp^^ + ) + + foreach(cmdapp ${cmdapps}) + # extract cmd name and dependencies + string(REPLACE "^^" "\\;" cmdapp_info ${cmdapp}) + set(cmdapp_info_list ${cmdapp_info}) + list(GET cmdapp_info_list 0 appname) + list(GET cmdapp_info_list 1 raw_dependencies) + string(REPLACE "_" "\\;" dependencies "${raw_dependencies}") + set(dependencies_list ${dependencies}) + + mitkFunctionCreateCommandLineApp( + NAME ${appname} + DEPENDS MitkCore MitkMatchPointRegistration ${dependencies_list} + PACKAGE_DEPENDS ITK + ) + endforeach() + +endif(BUILD_MatchPointCmdApps OR MITK_BUILD_ALL_APPS) diff --git a/Modules/MatchPointRegistration/cmdapps/StitchImagesMiniApp.cpp b/Modules/MatchPointRegistration/cmdapps/StitchImagesMiniApp.cpp new file mode 100644 index 0000000000..2178b3e399 --- /dev/null +++ b/Modules/MatchPointRegistration/cmdapps/StitchImagesMiniApp.cpp @@ -0,0 +1,202 @@ +/*============================================================================ + +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. + +============================================================================*/ + +// std includes +#include +#include + +// itk includes +#include "itksys/SystemTools.hxx" + +// CTK includes +#include "mitkCommandLineParser.h" + +// MITK includes +#include +#include +#include +#include +#include + +mitkCommandLineParser::StringContainerType inFilenames; +mitkCommandLineParser::StringContainerType regFilenames; +std::string outFileName; +std::string refGeometryFileName; + +std::vector images; +std::vector registrations; +mitk::BaseGeometry::Pointer refGeometry; +mitk::ImageMappingInterpolator::Type interpolatorType = mitk::ImageMappingInterpolator::Linear; +double paddingValue = 0; + +void setupParser(mitkCommandLineParser& parser) +{ + // set general information about your MiniApp + parser.setCategory("Mapping Tools"); + parser.setTitle("Stitch 3D Images"); + parser.setDescription("MiniApp that allows to map and stitch 3D images into a given output geometry."); + parser.setContributor("DKFZ MIC"); + //! [create parser] + + //! [add arguments] + // how should arguments be prefixed + parser.setArgumentPrefix("--", "-"); + // add each argument, unless specified otherwise each argument is optional + // see mitkCommandLineParser::addArgument for more information + parser.beginGroup("Required I/O parameters"); + parser.addArgument( + "inputs", "i", mitkCommandLineParser::StringList, "Input files", "Pathes to the input images that should be mapped and stitched", us::Any(), false, false, false, mitkCommandLineParser::Input); + parser.addArgument("output", + "o", + mitkCommandLineParser::File, + "Output file path", + "Path to the fused 3D+t image.", + us::Any(), + false, false, false, mitkCommandLineParser::Output); + parser.endGroup(); + + parser.beginGroup("Optional parameters"); + parser.addArgument("reference", + "x", + mitkCommandLineParser::File, + "Output reference image.", + "File path to an image that serves as reference 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("interpolator", "i", mitkCommandLineParser::Int, "Interpolator type", "Interpolator used for mapping the images. Default: 2; allowed values: 1: Nearest Neighbour, 2: Linear, 3: BSpline 3, 4: WSinc Hamming, 5: WSinc Welch", us::Any(2), true); + parser.addArgument("padding", "p", mitkCommandLineParser::Float, "Padding value", "Value used for output voxels that are not covered by any input image.", us::Any(0.), true); + parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); + parser.endGroup(); + //! [add arguments] +} + +bool configureApplicationSettings(std::map parsedArgs) +{ + if (parsedArgs.size() == 0) + return false; + + inFilenames = us::any_cast(parsedArgs["inputs"]); + outFileName = us::any_cast(parsedArgs["output"]); + + if (parsedArgs.count("reference")) + { + refGeometryFileName = us::any_cast(parsedArgs["reference"]); + } + + if (parsedArgs.count("registrations")) + { + regFilenames = us::any_cast(parsedArgs["registrations"]); + if (regFilenames.empty()) + { + regFilenames.resize(inFilenames.size()); + std::fill(regFilenames.begin(), regFilenames.end(), ""); + } + } + + if (parsedArgs.count("interpolator")) + { + auto interpolator = us::any_cast(parsedArgs["interpolator"]); + interpolatorType = static_cast(interpolator); + } + + if (parsedArgs.count("padding")) + { + paddingValue = us::any_cast(parsedArgs["padding"]); + } + + return true; +} + +int main(int argc, char* argv[]) +{ + mitkCommandLineParser parser; + setupParser(parser); + + mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (autoselect)" }, { "" }); + + const std::map& parsedArgs = parser.parseArguments(argc, argv); + if (!configureApplicationSettings(parsedArgs)) + { + return EXIT_FAILURE; + }; + + // Show a help message + if (parsedArgs.count("help") || parsedArgs.count("h")) + { + std::cout << parser.helpText(); + return EXIT_SUCCESS; + } + + if(regFilenames.size() != inFilenames.size()) + { + MITK_ERROR << "Cannot stitch inputs. The number of specified registrations does not match the number of inputs."; + return EXIT_FAILURE; + } + + //! [do processing] + try + { + std::cout << "Load images:" << std::endl; + + unsigned int index = 0; + for (auto path : inFilenames) + { + std::cout << "#"<(path, &readerFilterFunctor); + images.push_back(image.GetPointer()); + if (regFilenames[index].empty()) + { + std::cout << " associated registration: identity" << std::endl; + registrations.push_back(mitk::GenerateIdentityRegistration3D().GetPointer()); + } + else + { + std::cout << " associated registration: " << regFilenames[index] << std::endl; + auto reg = mitk::IOUtil::Load(path); + registrations.push_back(reg.GetPointer()); + } + ++index; + } + std::cout << "Padding value: " << paddingValue << std::endl; + std::cout << "Reference image: " << refGeometryFileName << std::endl << std::endl; + auto refImage = mitk::IOUtil::Load(refGeometryFileName, &readerFilterFunctor); + if (refImage.IsNotNull()) + { + refGeometry = refImage->GetGeometry(); + } + + + std::cout << "Stitch the the images ..." << std::endl; + + auto output = mitk::StitchImages(images, registrations, refGeometry,paddingValue,interpolatorType); + + std::cout << "Save output image: " << outFileName << std::endl; + + mitk::IOUtil::Save(output, outFileName); + + std::cout << "Processing finished." << std::endl; + + return EXIT_SUCCESS; + } + catch (const std::exception& e) + { + MITK_ERROR << e.what(); + return EXIT_FAILURE; + } + catch (...) + { + MITK_ERROR << "Unexpected error encountered."; + return EXIT_FAILURE; + } +} diff --git a/Modules/MatchPointRegistration/files.cmake b/Modules/MatchPointRegistration/files.cmake index 3f7a9b59a4..0bf01d264c 100644 --- a/Modules/MatchPointRegistration/files.cmake +++ b/Modules/MatchPointRegistration/files.cmake @@ -1,31 +1,32 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h") file(GLOB_RECURSE TPP_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*.tpp") set(CPP_FILES mitkMAPRegistrationWrapper.cpp mitkMAPRegistrationWrapperObjectFactory.cpp mitkRegEvaluationObjectFactory.cpp mitkRegEvaluationObject.cpp Helper/mitkUIDHelper.cpp Helper/mitkMAPAlgorithmHelper.cpp Helper/mitkMaskedAlgorithmHelper.cpp Helper/mitkRegistrationHelper.cpp Helper/mitkImageMappingHelper.cpp + Helper/mitkImageStitchingHelper.cpp Helper/mitkPointSetMappingHelper.cpp Helper/mitkResultNodeGenerationHelper.cpp Helper/mitkTimeFramesRegistrationHelper.cpp Rendering/mitkRegistrationWrapperMapper2D.cpp Rendering/mitkRegistrationWrapperMapper3D.cpp Rendering/mitkRegistrationWrapperMapperBase.cpp Rendering/mitkRegEvaluationMapper2D.cpp Rendering/mitkRegVisStyleProperty.cpp Rendering/mitkRegVisDirectionProperty.cpp Rendering/mitkRegVisColorStyleProperty.cpp Rendering/mitkRegVisPropertyTags.cpp Rendering/mitkRegVisHelper.cpp Rendering/mitkRegEvalStyleProperty.cpp Rendering/mitkRegEvalWipeStyleProperty.cpp ) set(MOC_H_FILES )