otbLSGRM.cxx 8.95 KB
Newer Older
remicres's avatar
remicres committed
1
2
3
4
5
6
7
8
9
10
11
12
#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"

remicres's avatar
remicres committed
13
// LSGRM
14
#include <iostream>
15
16
17
#include "lsgrmBaatzSegmenter.h"
#include "lsgrmSpringSegmenter.h"
#include "lsgrmFullLambdaScheduleSegmenter.h"
18
19
#include "lsgrmController.h"

20
21
22
// system tools
#include <itksys/SystemTools.hxx>

remicres's avatar
remicres committed
23
24
25
26
27
28
29
namespace otb
{

namespace Wrapper
{

class LSGRM : public Application
30
{
remicres's avatar
remicres committed
31
32
public:
  /** Standard class typedefs. */
33
  typedef LSGRM                         Self;
remicres's avatar
remicres committed
34
35
36
37
38
39
40
41
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);
  itkTypeMacro(LSGRM, Application);

42
43
44
45
46
47
  /** Useful typedefs */
  typedef otb::VectorImage<float, 2>                    ImageType;
  typedef lsgrm::BaatzSegmenter<ImageType>              BaatzSegmenterType;
  typedef lsgrm::SpringSegmenter<ImageType>             SpringSegmenterType;
  typedef lsgrm::FullLambdaScheduleSegmenter<ImageType> FLSSegmenterType;

remicres's avatar
remicres committed
48
49
private:

50
51
52
53
54
55
56
57
  /* Tiling mode choice */
  enum TilingMode
  {
    TILING_AUTO,
    TILING_USER,
    TILING_NONE
  };

58
59
60
61
62
63
64
65
  /* Criterion choice */
  enum Criterion
  {
    CRITERION_BAATZ,
    CRITERION_SPRING,
    CRITERION_FLS
  };

remicres's avatar
remicres committed
66
67
  void DoInit()
  {
68

69
    SetName("GenericRegionMerging");
remicres's avatar
remicres committed
70
71
    SetDescription("This application allows to use the Large Scale Generic Region Merging library "
        "(LSGRM) and provides currently 3 homogeneity criteria: Euclidean Distance, "
72
73
        "Full Lambda Schedule and Baatz & Schape criterion.");

74
    // Input and Output images
75
76
77
78
    AddParameter(ParameterType_InputImage, "in", "Input Image");
    AddParameter(ParameterType_OutputImage, "out", "Ouput Label Image");
    SetDefaultOutputPixelType("out", ImagePixelType_uint32);

79
80
81
82
83
    // 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");
84

85
    // Generic parameters
86
87
88
89
90
    AddParameter(ParameterType_Float, "threshold", "Threshold for the criterion");
    AddParameter(ParameterType_Int, "niter", "Maximum number of iterations");
    SetDefaultParameterInt("niter", 75);
    MandatoryOff("niter");

91
92
93
94
95
96
97
    // 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");
98
99

    // For large scale
100
    AddParameter(ParameterType_Directory, "tmpdir", "Directory for temporary files");
101
    MandatoryOff("tmpdir");
102
103
104
105
106
107
108
    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");
109
110
111

    AddParameter(ParameterType_Int, "memory", "Restrict memory use (mb)");
    MandatoryOff("memory");
remicres's avatar
remicres committed
112
113
114
115
116
117
  }

  void DoUpdateParameters()
  {
  }

118
119
120
121
122
123
124
125
126
127
128
  /*
   * 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
129
130
131
132
133
134
135
136
137
138
    std::string tmpdir;
    if (HasValue("tmpdir"))
      {
      tmpdir= GetParameterAsString("tmpdir");
      }
    else
      {
      tmpdir = itksys::SystemTools::GetFilenamePath(outfname);
      }

139
140
141
142
143
144
145
146
    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("/");
        }
remicres's avatar
remicres committed
147

148
149
150
151
152
153
      // 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);
remicres's avatar
remicres committed
154
      }
155

remicres's avatar
remicres committed
156
157

    // Return the prefix
158
159
160
161
    std::string prefix = tmpdir + outbfname;
    return prefix;
  }

162
163
164
  /*
   * This function sets the generic parameters of a controller and runs the segmentation
   */
remicres's avatar
remicres committed
165
166
167
168
169
170
171
172
173
174
  template<class TSegmenter>
  UInt32ImageType::Pointer SetGenericParametersAndRunSegmentation(const typename TSegmenter::ParamType params){

    // Instantiate the controller
    typedef typename lsgrm::Controller<TSegmenter> ControlerType;
    typename ControlerType::Pointer controller = ControlerType::New();

    // Set specific parameters
    controller->SetSpecificParameters(params);

175
176
    // Set input image
    controller->SetInputImage(GetParameterFloatVectorImage("in"));
remicres's avatar
remicres committed
177

178
179
180
    // Set threshold
    float thres = GetParameterFloat("threshold");
    controller->SetThreshold(thres*thres);
remicres's avatar
remicres committed
181

182
183
    // Set number of iterations
    controller->SetNumberOfIterations(GetParameterInt("niter"));
remicres's avatar
remicres committed
184

185
186
    // Set temporary files prefix
    controller->SetTemporaryFilesPrefix(this->GetTemporaryFilesPrefix());
remicres's avatar
remicres committed
187

188
    // Switch tiling mode
189
190
    int inputTilingMode = GetParameterInt("tiling");
    if (inputTilingMode == TILING_AUTO)
remicres's avatar
remicres committed
191
      {
192
193
      // Automatic mode
      controller->SetTilingModeAuto();
remicres's avatar
remicres committed
194
      }
195
    else if (inputTilingMode == TILING_USER)
remicres's avatar
remicres committed
196
      {
197
198
199
200
201
      // User mode
      controller->SetTilingModeUser();
      controller->SetTileWidth(GetParameterInt("tiling.user.sizex"));
      controller->SetTileHeight(GetParameterInt("tiling.user.sizey"));
      controller->SetNumberOfFirstIterations(GetParameterInt("tiling.user.nfirstiter"));
remicres's avatar
remicres committed
202
      }
203
204
    else if (inputTilingMode == TILING_NONE)
      {
205
206
      // None mode
      controller->SetTilingModeNone();
207
208
209
      }
    else
      {
210
211
212
213
214
215
216
217
      otbAppLogFATAL("Unknown tiling mode!");
      }

    // Input RAM value?
    if (HasValue("memory"))
      {
      otbAppLogINFO("Setting maximum memory to " << GetParameterInt("memory") << " MBytes");
      controller->SetInternalMemoryAvailable(GetParameterInt("memory"));
218
      }
remicres's avatar
remicres committed
219

remicres's avatar
remicres committed
220
    // Run the segmentation
221
    controller->RunSegmentation();
remicres's avatar
remicres committed
222

223
224
225
226
227
228
229
230
231
232
    // Get temporary files list
    m_TemporaryFilesList = controller->GetTemporaryFilesList();

    // Return the label image
    return controller->GetLabeledClusteredOutput();
  }

  void DoExecute()
  {
    /*
233
        TODO: the output directory in case the global graph cannot fit in memory (lsgrmController.txx)
234
235
236
237
238
239
240
241
242
243
244
245
     */

    // Input image
    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");
remicres's avatar
remicres committed
246
      labelImage = SetGenericParametersAndRunSegmentation<BaatzSegmenterType>(params);
247
248
249
      }
    else if (inputCriterion == CRITERION_SPRING)
      {
remicres's avatar
remicres committed
250
251
      grm::SpringParam params;
      labelImage = SetGenericParametersAndRunSegmentation<SpringSegmenterType>(params);
252
253
254
      }
    else if (inputCriterion == CRITERION_FLS)
      {
remicres's avatar
remicres committed
255
256
      grm::FLSParam params;
      labelImage = SetGenericParametersAndRunSegmentation<FLSSegmenterType>(params);
257
258
259
260
261
      }
    else
      {
      otbAppLogFATAL("Unknow criterion!")
      }
remicres's avatar
remicres committed
262

263
264
    std::cout << "Label image size: " << labelImage->GetLargestPossibleRegion() << std::endl;

remicres's avatar
remicres committed
265
266
267
268
269
270
    // Set output image projection, origin and spacing for labelImage
    labelImage->SetProjectionRef(inputImage->GetProjectionRef());
    labelImage->SetOrigin(inputImage->GetOrigin());
    labelImage->SetSpacing(inputImage->GetSpacing());
    SetParameterOutputImage<UInt32ImageType>("out", labelImage);

remicres's avatar
remicres committed
271
272
273
274
  }

  void AfterExecuteAndWriteOutputs()
  {
remicres's avatar
remicres committed
275
276
277
278
279
280
281

#ifdef OTB_USE_MPI
    // When MPI is activated, only the master thread proceed
    if (otb::MPIConfig::Instance()->GetMyRank() != 0)
      return;
#endif

282
283
284
285
286
287
288
289
    // 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) );
        }
      }
remicres's avatar
remicres committed
290
291
  }

292
293
private:
  std::vector<std::string> m_TemporaryFilesList;
294
  UInt32ImageType::Pointer labelImage;
295

remicres's avatar
remicres committed
296
297
298
299
300
}; // app class
} // end of namespace wrapper
} // end of namespace otb

OTB_APPLICATION_EXPORT(otb::Wrapper::LSGRM)