otbLSGRM.cxx 8.12 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
    SetName("GenericRegionMerging");
remicres's avatar
remicres committed
69
70
    SetDescription("This application allows to use the Large Scale Generic Region Merging library "
        "(LSGRM) and provides currently 3 homogeneity criteria: Euclidean Distance, "
71
72
        "Full Lambda Schedule and Baatz & Schape criterion.");

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

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

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

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

    // For large scale
99
    AddParameter(ParameterType_Directory, "tmpdir", "Directory for temporary files");
100
101
102
103
104
105
106
107
    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");
    AddParameter(ParameterType_Int, "tiling.user.memory", "Available memory");
    AddChoice("tiling.none", "No tiling layout");
remicres's avatar
remicres committed
108
109
110
111
112
113
  }

  void DoUpdateParameters()
  {
  }

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  /*
   * 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 = GetParameterAsString("tmpdir");
    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("/");
        }
      }
    std::string prefix = tmpdir + outbfname;
    return prefix;
  }

139
140
141
  /*
   * This function sets the generic parameters of a controller and runs the segmentation
   */
remicres's avatar
remicres committed
142
143
144
145
146
147
148
149
150
151
  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);

152
153
    // Set input image
    controller->SetInputImage(GetParameterFloatVectorImage("in"));
remicres's avatar
remicres committed
154

155
156
157
    // Set threshold
    float thres = GetParameterFloat("threshold");
    controller->SetThreshold(thres*thres);
remicres's avatar
remicres committed
158

159
160
    // Set number of iterations
    controller->SetNumberOfIterations(GetParameterInt("niter"));
remicres's avatar
remicres committed
161

162
163
    // Set temporary files prefix
    controller->SetTemporaryFilesPrefix(this->GetTemporaryFilesPrefix());
remicres's avatar
remicres committed
164

165
    // Switch tiling mode
166
167
    int inputTilingMode = GetParameterInt("tiling");
    if (inputTilingMode == TILING_AUTO)
remicres's avatar
remicres committed
168
      {
169
170
      // Automatic mode
      controller->SetTilingModeAuto();
remicres's avatar
remicres committed
171
      }
172
    else if (inputTilingMode == TILING_USER)
remicres's avatar
remicres committed
173
      {
174
175
176
177
178
179
      // User mode
      controller->SetTilingModeUser();
      controller->SetTileWidth(GetParameterInt("tiling.user.sizex"));
      controller->SetTileHeight(GetParameterInt("tiling.user.sizey"));
      controller->SetNumberOfFirstIterations(GetParameterInt("tiling.user.nfirstiter"));
      controller->SetInternalMemoryAvailable(GetParameterInt("tiling.user.memory"));
remicres's avatar
remicres committed
180
      }
181
182
    else if (inputTilingMode == TILING_NONE)
      {
183
184
      // None mode
      controller->SetTilingModeNone();
185
186
187
      }
    else
      {
188
      otbAppLogFATAL("Unknow tiling mode!");
189
      }
remicres's avatar
remicres committed
190

remicres's avatar
remicres committed
191
    // Run the segmentation
192
    controller->RunSegmentation();
remicres's avatar
remicres committed
193

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
    // Get temporary files list
    m_TemporaryFilesList = controller->GetTemporaryFilesList();

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

  void DoExecute()
  {
    /*
        To add:
        the output directory in case the global graph cannot fit in memory
     */

    // Input image
    ImageType::Pointer inputImage = GetParameterFloatVectorImage("in");

    // Output image
    UInt32ImageType::Pointer labelImage = UInt32ImageType::New();

    // 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
221
      labelImage = SetGenericParametersAndRunSegmentation<BaatzSegmenterType>(params);
222
223
224
      }
    else if (inputCriterion == CRITERION_SPRING)
      {
remicres's avatar
remicres committed
225
226
      grm::SpringParam params;
      labelImage = SetGenericParametersAndRunSegmentation<SpringSegmenterType>(params);
227
228
229
      }
    else if (inputCriterion == CRITERION_FLS)
      {
remicres's avatar
remicres committed
230
231
      grm::FLSParam params;
      labelImage = SetGenericParametersAndRunSegmentation<FLSSegmenterType>(params);
232
233
234
235
236
      }
    else
      {
      otbAppLogFATAL("Unknow criterion!")
      }
remicres's avatar
remicres committed
237
238
239
240
241
242
243

    // 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
244
245
246
247
  }

  void AfterExecuteAndWriteOutputs()
  {
248
249
250
251
252
253
254
255
    // 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
256
257
  }

258
259
260
private:
  std::vector<std::string> m_TemporaryFilesList;

remicres's avatar
remicres committed
261
262
263
264
265
}; // app class
} // end of namespace wrapper
} // end of namespace otb

OTB_APPLICATION_EXPORT(otb::Wrapper::LSGRM)