diff --git a/Applications/Segmentation/otbSegmentation.cxx b/Applications/Segmentation/otbSegmentation.cxx
index 1eb6a8a6a04258dec9a49e150043258877c93bbc..325713a231a1dfdf863ae6730e7805ffadae2109 100644
--- a/Applications/Segmentation/otbSegmentation.cxx
+++ b/Applications/Segmentation/otbSegmentation.cxx
@@ -29,6 +29,13 @@
 #include "otbVectorImageToAmplitudeImageFilter.h"
 #include "itkGradientMagnitudeImageFilter.h"
 #include "otbWatershedSegmentationFilter.h"
+#include "otbMultiScaleConvexOrConcaveClassificationFilter.h"
+#include "itkBinaryBallStructuringElement.h"
+#include "otbMorphologicalOpeningProfileFilter.h"
+#include "otbMorphologicalClosingProfileFilter.h"
+#include "otbProfileToProfileDerivativeFilter.h"
+#include "otbProfileDerivativeToMultiScaleCharacteristicsFilter.h"
+#include "itkScalarConnectedComponentImageFilter.h"
 
 // Large scale vectorization framework
 #include "otbStreamingImageToOGRLayerSegmentationFilter.h"
@@ -38,7 +45,6 @@
 #include "otbOGRLayerStreamStitchingFilter.h"
 
 #include "otbGeoInformationConversion.h"
-
 namespace otb
 {
 namespace Wrapper
@@ -79,6 +85,11 @@ public:
    FunctorType,
    MaskImageType >                        ConnectedComponentSegmentationFilterType;
 
+  typedef itk::ScalarConnectedComponentImageFilter
+  <LabelImageType,
+   LabelImageType>                        LabeledConnectedComponentSegmentationFilterType;
+
+
   // Watershed
   typedef otb::VectorImageToAmplitudeImageFilter
   <FloatVectorImageType,
@@ -90,6 +101,18 @@ public:
   typedef otb::WatershedSegmentationFilter
   <FloatImageType,LabelImageType>         WatershedSegmentationFilterType;
 
+  // Geodesic morphology multiscale segmentation
+  typedef itk::BinaryBallStructuringElement<FloatImageType::PixelType, 2> StructuringElementType;
+  typedef otb::MorphologicalOpeningProfileFilter<FloatImageType, FloatImageType, StructuringElementType>
+  OpeningProfileFilterType;
+  typedef otb::MorphologicalClosingProfileFilter<FloatImageType, FloatImageType, StructuringElementType>
+  ClosingProfileFilterType;
+  typedef otb::ProfileToProfileDerivativeFilter<FloatImageType, FloatImageType> DerivativeFilterType;
+  typedef otb::ProfileDerivativeToMultiScaleCharacteristicsFilter<FloatImageType,FloatImageType, LabelImageType>
+  MultiScaleCharacteristicsFilterType;
+  typedef otb::MultiScaleConvexOrConcaveClassificationFilter<FloatImageType,LabelImageType> MultiScaleClassificationFilterType;
+  
+
 
   // mask filter
   typedef otb::MaskMuParserFilter
@@ -112,6 +135,12 @@ public:
   <FloatVectorImageType,
    ConnectedComponentSegmentationFilterType>
   ConnectedComponentStreamingVectorizedSegmentationOGRType;
+  typedef otb::StreamingImageToOGRLayerSegmentationFilter
+  <LabelImageType,
+   LabeledConnectedComponentSegmentationFilterType>
+  LabeledConnectedComponentStreamingVectorizedSegmentationOGRType;
+
+
 
   typedef otb::OGRLayerStreamStitchingFilter
   <FloatVectorImageType>                  FusionFilterType;
@@ -134,7 +163,7 @@ private:
 
     // Documentation
     SetDocName("Segmentation");
-    SetDocLongDescription("This application allows to perform various segmentation algorithms on an multispectral image."
+    SetDocLongDescription("This application allows to perform various segmentation algorithms on a multispectral image."
                           "Available segmentation algorithms are two different versions of Mean-Shift segmentation algorithm (one being multi-threaded),"
                           " simple pixel based connected components according to a user-defined criterion, and watershed from the gradient of the intensity"
                           " (norm of spectral bands vector). The application has two different modes that affects the nature of its output.\n\nIn raster mode,"
@@ -241,6 +270,22 @@ private:
     AddChoice("mode.raster", "Standard segmentation with labeled raster output");
     SetParameterDescription("mode.raster","In this mode, the application will output a standard labeled raster. This mode can not handle large data.");
 
+    // GeoMorpho
+    AddChoice("filter.geomorpho","Multiscale Geodesic Morphology");
+
+    AddParameter(ParameterType_Int,"filter.geomorpho.size","Profile Size");
+    SetParameterDescription("filter.geomorpho.size","TODO");
+    SetDefaultParameterInt("filter.geomorpho.size",5);
+    AddParameter(ParameterType_Int,"filter.geomorpho.step","Profile Step");
+    SetParameterDescription("filter.geomorpho.step","TODO");
+    SetDefaultParameterInt("filter.geomorpho.step",1);
+    AddParameter(ParameterType_Int,"filter.geomorpho.start","Profile Start");
+    SetParameterDescription("filter.geomorpho.start","TODO");
+    SetDefaultParameterInt("filter.geomorpho.start",1);
+    AddParameter(ParameterType_Float,"filter.geomorpho.sigma","Sigma for decision rule");
+    SetParameterDescription("filter.geomorpho.sigma","TODO");
+    SetDefaultParameterFloat("filter.geomorpho.sigma",1.);
+
     //Raster mode parameters
     AddParameter(ParameterType_OutputImage,  "mode.raster.out",    "Output labeled image");
     SetParameterDescription( "mode.raster.out", "The output labeled image.");
@@ -345,7 +390,7 @@ private:
     typedef  TSegmentationFilter             SegmentationFilterType;
     typedef  typename SegmentationFilterType::Pointer SegmentationFilterPointerType;
     typedef otb::StreamingImageToOGRLayerSegmentationFilter
-      <FloatVectorImageType,
+      <TInputImage,
        SegmentationFilterType>          StreamingVectorizedSegmentationOGRType;
 
     // Retrieve tile size parameter
@@ -637,6 +682,73 @@ private:
                                                                                                           gradientMagnitudeFilter->GetOutput(),
                                                                                                           layer, 0);
             }
+
+        else
+          if (segType == "geomorpho")
+            {
+            otbAppLogINFO(<<"Using multiscale geodesic morphology segmentation."<<std::endl);
+
+            
+            unsigned int profileSize = GetParameterInt("filter.geomorpho.size");
+            unsigned int initialValue = GetParameterInt("filter.geomorpho.start");
+            unsigned int step = GetParameterInt("filter.geomorpho.step");
+            double       sigma = GetParameterFloat("filter.geomorpho.sigma");
+
+
+            AmplitudeFilterType::Pointer amplitudeFilter = AmplitudeFilterType::New();
+
+            amplitudeFilter->SetInput(this->GetParameterFloatVectorImage("in"));
+
+            OpeningProfileFilterType::Pointer oprofileFilter = OpeningProfileFilterType::New();
+            oprofileFilter->SetInput(amplitudeFilter->GetOutput());
+            oprofileFilter->SetProfileSize(profileSize);
+            oprofileFilter->SetInitialValue(initialValue);
+            oprofileFilter->SetStep(step);
+            
+            ClosingProfileFilterType::Pointer cprofileFilter = ClosingProfileFilterType::New();
+            cprofileFilter->SetInput(amplitudeFilter->GetOutput());
+            cprofileFilter->SetProfileSize(profileSize);
+            cprofileFilter->SetInitialValue(initialValue);
+            cprofileFilter->SetStep(step);
+            
+            DerivativeFilterType::Pointer oderivativeFilter = DerivativeFilterType::New();
+            oderivativeFilter->SetInput(oprofileFilter->GetOutput());
+            
+            DerivativeFilterType::Pointer cderivativeFilter = DerivativeFilterType::New();
+            cderivativeFilter->SetInput(cprofileFilter->GetOutput());
+            
+            MultiScaleCharacteristicsFilterType::Pointer omsCharFilter = MultiScaleCharacteristicsFilterType::New();
+            omsCharFilter->SetInput(oderivativeFilter->GetOutput());
+            omsCharFilter->SetInitialValue(initialValue);
+            omsCharFilter->SetStep(step);
+            
+            MultiScaleCharacteristicsFilterType::Pointer cmsCharFilter = MultiScaleCharacteristicsFilterType::New();
+            cmsCharFilter->SetInput(cderivativeFilter->GetOutput());
+            cmsCharFilter->SetInitialValue(initialValue);
+            cmsCharFilter->SetStep(step);
+            
+            MultiScaleClassificationFilterType::Pointer classificationFilter = MultiScaleClassificationFilterType::New();
+            classificationFilter->SetOpeningProfileDerivativeMaxima(omsCharFilter->GetOutput());
+            classificationFilter->SetOpeningProfileCharacteristics(omsCharFilter->GetOutputCharacteristics());
+            classificationFilter->SetClosingProfileDerivativeMaxima(cmsCharFilter->GetOutput());
+            classificationFilter->SetClosingProfileCharacteristics(cmsCharFilter->GetOutputCharacteristics());
+            classificationFilter->SetSigma(sigma);
+            classificationFilter->SetLabelSeparator(initialValue + profileSize * step);
+            
+            LabeledConnectedComponentStreamingVectorizedSegmentationOGRType::Pointer
+              ccVectorizationFilter = LabeledConnectedComponentStreamingVectorizedSegmentationOGRType::New();
+            
+            if (HasValue("mode.vector.inmask"))
+              {
+              ccVectorizationFilter->GetSegmentationFilter()->SetMaskImage(
+                this->GetParameterUInt32Image("mode.vector.inmask"));
+        }
+
+            streamSize = GenericApplySegmentation<LabelImageType, LabeledConnectedComponentSegmentationFilterType> (
+        ccVectorizationFilter,                                                                      classificationFilter->GetOutput(),
+                                                                                                             layer, 0);
+            
+            }
           else
             {
             otbAppLogFATAL(<<"non defined filtering method "<<GetParameterInt("filter")<<std::endl);
diff --git a/Code/UtilitiesAdapters/OssimAdapters/otbSensorModelAdapter.cxx b/Code/UtilitiesAdapters/OssimAdapters/otbSensorModelAdapter.cxx
index a8df4fbbb701be967a7c7f35f23cd209500b11bc..c7ef65c8fe4e731accbd5a833889d0e71de2f97f 100644
--- a/Code/UtilitiesAdapters/OssimAdapters/otbSensorModelAdapter.cxx
+++ b/Code/UtilitiesAdapters/OssimAdapters/otbSensorModelAdapter.cxx
@@ -120,7 +120,9 @@ void SensorModelAdapter::ForwardTransformPoint(double x, double y, double z,
 
     otbMsgDevMacro(<< "USING DEM ! ");
 
-    while ((diffHeight > m_Epsilon) && (nbIter < m_NbIter))
+    bool nanHeight = false;
+
+    while (!nanHeight && (diffHeight > m_Epsilon) && (nbIter < m_NbIter))
       {
       otbMsgDevMacro(<< "Iter " << nbIter);
 
@@ -128,10 +130,18 @@ void SensorModelAdapter::ForwardTransformPoint(double x, double y, double z,
 
       heightTmp = this->m_DEMHandler->GetHeightAboveMSL(lon, lat);
 
-      this->m_SensorModel->lineSampleHeightToWorld(ossimPoint, heightTmp, ossimGPointRef);
-
+      if(ossim::isnan(heightTmp))
+        {
+        nanHeight = true;
+        this->m_SensorModel->lineSampleToWorld(ossimPoint, ossimGPointRef);
+        }
+      else
+        {
+        this->m_SensorModel->lineSampleHeightToWorld(ossimPoint, heightTmp, ossimGPointRef);
+        }
+      
       diffHeight = fabs(heightTmp - height);
-
+      
       ++nbIter;
       }
     ossimGPoint = ossimGPointRef;
@@ -245,4 +255,41 @@ double SensorModelAdapter::Optimize()
   return precision;
 }
 
+bool SensorModelAdapter::ReadGeomFile(const std::string & infile)
+{
+  ossimKeywordlist geom;
+
+  geom.add(infile.c_str());
+  
+  m_SensorModel = ossimSensorModelFactory::instance()->createProjection(geom);
+  
+  if (m_SensorModel == NULL)
+    {
+    m_SensorModel = ossimplugins::ossimPluginProjectionFactory::instance()->createProjection(geom);
+    }
+  
+  return (m_SensorModel != NULL);
+}
+
+bool SensorModelAdapter::WriteGeomFile(const std::string & outfile)
+{
+  // If tie points and model are allocated
+  if(m_SensorModel != NULL)
+    {
+    // try to retrieve a sensor model
+    ossimSensorModel * sensorModel = NULL;
+    sensorModel = dynamic_cast<ossimSensorModel *>(m_SensorModel);
+
+    ossimKeywordlist geom;
+
+    bool success = sensorModel->saveState(geom);
+
+    if(success)
+      {
+      return geom.write(outfile.c_str());
+      }
+    }
+  return false;
+}
+
 } // namespace otb
diff --git a/Code/UtilitiesAdapters/OssimAdapters/otbSensorModelAdapter.h b/Code/UtilitiesAdapters/OssimAdapters/otbSensorModelAdapter.h
index c5f67ee978161e16bd0bf948eb7c97bd41cf23fd..150feab485f9bf1fdbb2085fb01d393de9b8fe03 100644
--- a/Code/UtilitiesAdapters/OssimAdapters/otbSensorModelAdapter.h
+++ b/Code/UtilitiesAdapters/OssimAdapters/otbSensorModelAdapter.h
@@ -86,6 +86,12 @@ public:
   /** Is sensor model valid method. return false if the m_SensorModel is null*/
   bool IsValidSensorModel();
 
+  /** Read geom file and instanciate sensor model */
+  bool ReadGeomFile(const std::string & infile);
+  
+  /** Write geom file corresponding to sensor model */
+  bool WriteGeomFile(const std::string& outfile);
+
 protected:
   SensorModelAdapter();
   virtual ~SensorModelAdapter();