#include "itkFixedArray.h" #include "itkObjectFactory.h" // Elevation handler #include "otbWrapperElevationParametersHandler.h" #include "otbWrapperApplicationFactory.h" // Application engine #include "otbStandardFilterWatcher.h" #include "itkFixedArray.h" #include "itkImageSource.h" // LSGRM #include #include "lsgrmBaatzSegmenter.h" #include "lsgrmSpringSegmenter.h" #include "lsgrmFullLambdaScheduleSegmenter.h" #include "lsgrmController.h" // Graph to label image (streaming version) #include "otbStreamingGraphToImageFilter.h" #include "otbStreamingImageVirtualWriter.h" // system tools #include namespace otb { namespace Wrapper { class LSGRM : public Application { public: /** Standard class typedefs. */ typedef LSGRM Self; typedef Application Superclass; typedef itk::SmartPointer Pointer; typedef itk::SmartPointer ConstPointer; /** Standard macro */ itkNewMacro(Self); itkTypeMacro(LSGRM, Application); /** Useful typedefs */ typedef otb::VectorImage ImageType; typedef lsgrm::BaatzSegmenter BaatzSegmenterType; typedef lsgrm::SpringSegmenter SpringSegmenterType; typedef lsgrm::FullLambdaScheduleSegmenter FLSSegmenterType; private: /* Tiling mode choice */ enum TilingMode { TILING_AUTO, TILING_USER, TILING_NONE }; /* Criterion choice */ enum Criterion { CRITERION_BAATZ, CRITERION_SPRING, CRITERION_FLS }; void DoInit() { SetName("GenericRegionMerging"); SetDescription("This application allows to use the Large Scale Generic Region Merging library " "(LSGRM) and provides currently 3 homogeneity criteria: Euclidean Distance, " "Full Lambda Schedule and Baatz & Schape criterion."); // Input and Output images AddParameter(ParameterType_InputImage, "in", "Input Image"); AddParameter(ParameterType_OutputImage, "out", "Ouput Label Image"); SetDefaultOutputPixelType("out", ImagePixelType_uint32); // Criterion choice AddParameter(ParameterType_Choice, "criterion", "Homogeneity criterion to use"); AddChoice("criterion.bs", "Baatz & Schape"); AddChoice("criterion.ed", "Euclidean Distance"); AddChoice("criterion.fls", "Full Lambda Schedule"); // Generic parameters AddParameter(ParameterType_Float, "threshold", "Threshold for the criterion"); AddParameter(ParameterType_Int, "niter", "Maximum number of iterations"); SetDefaultParameterInt("niter", 75); MandatoryOff("niter"); // Specific parameters for Baatz & Schape AddParameter(ParameterType_Float, "criterion.bs.cw", "Weight for the spectral homogeneity"); SetDefaultParameterFloat("criterion.bs.cw", 0.5); MandatoryOff("criterion.bs.cw"); AddParameter(ParameterType_Float, "criterion.bs.sw", "Weight for the spatial homogeneity"); SetDefaultParameterFloat("criterion.bs.sw", 0.5); MandatoryOff("criterion.bs.sw"); // For large scale AddParameter(ParameterType_Directory, "tmpdir", "Directory for temporary files"); MandatoryOff("tmpdir"); AddParameter(ParameterType_Choice, "tiling", "Tiling layout for the large scale segmentation"); AddChoice("tiling.auto", "Automatic tiling layout"); AddChoice("tiling.user", "User tiling layout"); AddParameter(ParameterType_Int, "tiling.user.sizex", "Tiles width"); AddParameter(ParameterType_Int, "tiling.user.sizey", "Tiles height"); AddParameter(ParameterType_Int, "tiling.user.nfirstiter", "Number of first iterations"); AddChoice("tiling.none", "No tiling layout"); AddParameter(ParameterType_Int, "memory", "Restrict memory use (mb)"); MandatoryOff("memory"); AddParameter(ParameterType_Bool, "resume", "Activate resume mode"); SetDefaultParameterInt("resume", 0); MandatoryOff("resume"); } void DoUpdateParameters() { } /* * Return a prefix for temporary files */ std::string GetTemporaryFilesPrefix() { // Get output filename (without extension) std::string outfname = GetParameterString("out"); std::string outbfname = itksys::SystemTools::GetFilenameWithoutExtension(outfname.c_str()); // Get specified temporary directory std::string tmpdir; if (HasValue("tmpdir")) { tmpdir= GetParameterAsString("tmpdir"); } else { tmpdir = itksys::SystemTools::GetFilenamePath(outfname); } if (!tmpdir.empty()) { // A temporary directory is specified: we check that it ends with a POSIX separator if (tmpdir[tmpdir.size()-1] != '/') { // If not, we add the separator tmpdir.append("/"); } // Check that the directory exists if (!itksys::SystemTools::FileExists(tmpdir.c_str(),false)) { otbAppLogFATAL("The directory " << tmpdir << " does not exist."); } otbAppLogINFO("Using temporary directory " << tmpdir); } // Return the prefix std::string prefix = tmpdir + outbfname; return prefix; } /* * This function sets the generic parameters of a controller and runs the segmentation */ template void SetGenericParametersAndRunSegmentation(const typename TSegmenter::ParamType params){ // Instantiate the controller typedef typename lsgrm::Controller ControlerType; typename ControlerType::Pointer controller = ControlerType::New(); using GraphType = typename ControlerType::GraphType; // Set specific parameters controller->SetSpecificParameters(params); // Set input image ImageType::Pointer inputImage = GetParameterFloatVectorImage("in"); controller->SetInputImage(inputImage); // Set threshold float thres = GetParameterFloat("threshold"); controller->SetThreshold(thres*thres); // Set number of iterations controller->SetNumberOfIterations(GetParameterInt("niter")); // Set temporary files prefix controller->SetTemporaryFilesPrefix(this->GetTemporaryFilesPrefix()); // Switch tiling mode int inputTilingMode = GetParameterInt("tiling"); if (inputTilingMode == TILING_AUTO) { // Automatic mode controller->SetTilingModeAuto(); } else if (inputTilingMode == TILING_USER) { // User mode controller->SetTilingModeUser(); controller->SetTileWidth(GetParameterInt("tiling.user.sizex")); controller->SetTileHeight(GetParameterInt("tiling.user.sizey")); controller->SetNumberOfFirstIterations(GetParameterInt("tiling.user.nfirstiter")); } else if (inputTilingMode == TILING_NONE) { // None mode controller->SetTilingModeNone(); } else { otbAppLogFATAL("Unknown tiling mode!"); } // Input RAM value? if (HasValue("memory")) { otbAppLogINFO("Setting maximum memory to " << GetParameterInt("memory") << " MBytes"); controller->SetInternalMemoryAvailable(GetParameterInt("memory")); } // Resume mode? if (GetParameterInt("resume")) { controller->SetResumingMode(); } // Run the segmentation controller->RunSegmentation(); // Prepare the label image source typedef lsgrm::StreamingGraphToImageFilter LabelImageSourceType; typename LabelImageSourceType::Pointer labelImageSource = LabelImageSourceType::New(); labelImageSource->SetGraph(controller->GetOutputGraph()); labelImageSource->SetOutputSize(inputImage->GetLargestPossibleRegion().GetSize()); labelImageSource->SetOutputOrigin(inputImage->GetOrigin()); labelImageSource->SetOutputSpacing(inputImage->GetSignedSpacing()); labelImageSource->SetOutputProjectionRef(inputImage->GetProjectionRef()); labelImageSource->GenerateOutputInformation(); m_LabelImageSource = static_cast*>(labelImageSource); SetParameterOutputImage("out", m_LabelImageSource->GetOutput()); // TODO: find an intelligent value of RAM if (dynamic_cast(GetParameterByKey("out"))) { OutputImageParameter* paramDown = dynamic_cast(GetParameterByKey("out")); paramDown->SetRAMValue(1024); } // Get temporary files list m_TemporaryFilesList = controller->GetTemporaryFilesList(); } void DoExecute() { ImageType::Pointer inputImage = GetParameterFloatVectorImage("in"); // Switch criterion int inputCriterion = GetParameterInt("criterion"); if (inputCriterion == CRITERION_BAATZ) { grm::BaatzParam params; params.m_SpectralWeight = GetParameterFloat("criterion.bs.cw"); params.m_ShapeWeight = GetParameterFloat("criterion.bs.sw"); SetGenericParametersAndRunSegmentation(params); } else if (inputCriterion == CRITERION_SPRING) { grm::SpringParam params; SetGenericParametersAndRunSegmentation(params); } else if (inputCriterion == CRITERION_FLS) { grm::FLSParam params; SetGenericParametersAndRunSegmentation(params); } else { otbAppLogFATAL("Unknow criterion!") } } void AfterExecuteAndWriteOutputs() { // Delete temporary files for (unsigned int i = 0 ; i < m_TemporaryFilesList.size() ; i++) { if( remove(m_TemporaryFilesList.at(i).c_str() ) != 0 ) { otbAppLogWARNING( "Error deleting file " << m_TemporaryFilesList.at(i) ); } } } private: std::vector m_TemporaryFilesList; itk::ImageSource::Pointer m_LabelImageSource; }; // app class } // end of namespace wrapper } // end of namespace otb OTB_APPLICATION_EXPORT(otb::Wrapper::LSGRM)