Commit e38ade22 authored by Guillaume Pasero's avatar Guillaume Pasero

MRG: Synchronize with branch 'develop'

parents 4eea72f2 e71ddd79
......@@ -22,6 +22,8 @@ include(CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS})
unset(OTB_HAS_CXX11 CACHE)
CHECK_CXX_SOURCE_COMPILES("
#ifdef _MSC_VER
#if _MSC_VER <= 1700
......
......@@ -149,10 +149,10 @@ def FindLengthOfLargestColumnText(app,paramlist):
else:
if colLength[0] < len(param):
colLength[0] = len(param)
lenpdescr = len(app.GetParameterName(param))
lenpdescr = len(GenerateParameterType(app, param))
if colLength[2] < lenpdescr:
colLength[2] = lenpdescr
lenptype = len(GenerateParameterType(app,param))
lenptype = len(app.GetParameterName(param))
if colLength[1] < lenptype:
colLength[1] = lenptype
return colLength
......@@ -181,14 +181,14 @@ def MakeText(text, size):
def GenerateParametersTable(app,paramlist):
colLength = FindLengthOfLargestColumnText(app, paramlist)
output = linesep + ".. [#] Table: Parameters table for " + ConvertString(app.GetDocName()) + "." + linesep + linesep
headerlist = ["Parameter Key", "Parameter Type", "Parameter Description"]
headerlist = ["Parameter Key", "Parameter Name", "Parameter Type"]
for i in xrange(len(headerlist)):
colLength[i] = len(headerlist[i]) if colLength[i] < len(headerlist[i]) else colLength[i]
output += RstTableHeading(headerlist, colLength)
for param in paramlist:
output += MakeText(param, colLength[0])
output += MakeText(GenerateParameterType(app,param), colLength[1])
output += MakeText(GenerateParameterType(app,param), colLength[2])
output += MakeText(app.GetParameterName(param), colLength[1])
output += MakeText(GenerateParameterType(app, param), colLength[2])
output += '|' + linesep
output += RstTableHeaderLine(headerlist, colLength, '-')
if app.GetParameterType(param) == otbApplication.ParameterType_Choice:
......
......@@ -145,9 +145,9 @@ the *MeanShiftSmoothing* application:
::
otbcli_MeanShiftSmoothing -in input_image
otbcli_MeanShiftSmoothing -in input_image.tif
-fout filtered_range.tif
-foutpos filtered_spat.tif
-foutpos filtered_spatial.tif
-ranger 30
-spatialr 5
-maxiter 10
......@@ -173,7 +173,7 @@ so, the *LSMSSegmentation* will process them by tiles whose dimensions
are defined by the *tilesizex* and *tilesizey* parameters, and by
writing intermediate images to disk, thus keeping the memory consumption
very low throughout the process. The segmentation will group together
adjacent pixels whose range distance is below the *ranger* parameter and
neighboring pixels whose range distance is below the *ranger* parameter and
(optionally) spatial distance is below the *spatialr* parameter.
::
......@@ -250,7 +250,7 @@ projection, so does the output GIS file).
::
otbcli_LSMSVectorization -in input_image
otbcli_LSMSVectorization -in input_image.tif
-inseg segmentation_merged.tif
-out segmentation_merged.shp
-tilesizex 256
......
......@@ -4,10 +4,10 @@ Classification
Pixel based classification
--------------------------
Orfeo ToolBox ships with a set of application to perform supervised
pixel-based image classification. This framework allows to learn from
multiple images, and using several machine learning method such as
SVM, Bayes, KNN, Random Forests, Artificial Neural Network, and
Orfeo ToolBox ships with a set of application to perform supervised or
unsupervised pixel-based image classification. This framework allows
to learn from multiple images, and using several machine learning method
such as SVM, Bayes, KNN, Random Forests, Artificial Neural Network, and
others...(see application help of ``TrainImagesClassifier`` and
``TrainVectorClassifier`` for further details about all the available
classifiers). Here is an overview of the complete workflow:
......@@ -347,8 +347,9 @@ using the ``TrainVectorClassifier`` application.
-feat band_0 band_1 band_2 band_3 band_4 band_5 band_6
The ``-classifier`` parameter allows to choose which machine learning
model algorithm to train. Please refer to the
``TrainVectorClassifier`` application reference documentation.
model algorithm to train. You have the possibility to do the unsupervised
classification,for it, you must to choose the Shark kmeans classifier.
Please refer to the ``TrainVectorClassifier`` application reference documentation.
In case of multiple samples files, you can add them to the ``-io.vd``
parameter (see `Working with several images`_ section).
......@@ -409,6 +410,11 @@ class too, based on the
`ConfusionMatrixCalculator <http://www.orfeo-toolbox.org/doxygen-current/classotb_1_1ConfusionMatrixCalculator.html>`_
class.
If you have made an unsupervised classification, it must be specified
to the ``ConputeConfusionMatrix`` application. In this case, a contingency table
have to be create rather than a confusion matrix. For further details,
see ``format`` parameter in the application help of *ConputeConfusionMatrix*.
::
otbcli_ComputeConfusionMatrix -in labeled_image.tif
......
......@@ -253,6 +253,26 @@ IMPORTANT: Note that you'll probably need to "quote" the filename.
\item Select the JPEG2000 sub-resolution image to read
\item 0 by default
\end{itemize}
\item \begin{verbatim}&bands=r1,r2,...,rn\end{verbatim}
\begin{itemize}
\item Select a subset of bands from the input image
\item The syntax is inspired by Python indexing syntax with
bands=r1,r2,r3,...,rn where each ri is a band range that can be :
\begin{itemize}
\item a single index (1-based) :
\begin{itemize}
\item $'2'$ means 2nd band
\item $'-1'$ means last band
\end{itemize}
\item or a range of bands :
\begin{itemize}
\item $'3:'$ means 3rd band until the last one
\item $':-2'$ means the first bands until the second to last
\item $'2:4'$ means bands 2,3 and 4
\end{itemize}
\end{itemize}
\item empty by default (all bands are read from the input image)
\end{itemize}
\item \begin{verbatim}&skipcarto=<(bool)true>\end{verbatim}
\begin{itemize}
\item Skip the cartographic information
......@@ -339,8 +359,8 @@ IMPORTANT: Note that you'll probably need to "quote" the filename.
\item The region must be set with 4 unsigned integers (the separator used is
the colon ':'). Values are:
\begin{itemize}
\item startx: first index on X
\item starty: first index on Y
\item startx: first index on X (starting with 0)
\item starty: first index on Y (starting with 0)
\item sizex: size along X
\item sizey: size along Y
\end{itemize}
......@@ -349,6 +369,26 @@ IMPORTANT: Note that you'll probably need to "quote" the filename.
itk::Size classes. The origin of the region within the image with which it
is associated is defined by Index
\end{itemize}
\item \begin{verbatim}&bands=r1,r2,...,rn\end{verbatim}
\begin{itemize}
\item Select a subset of bands from the output image
\item The syntax is inspired by Python indexing syntax with
bands=r1,r2,r3,...,rn where each ri is a band range that can be :
\begin{itemize}
\item a single index (1-based) :
\begin{itemize}
\item $'2'$ means 2nd band
\item $'-1'$ means last band
\end{itemize}
\item or a range of bands :
\begin{itemize}
\item $'3:'$ means 3rd band until the last one
\item $':-2'$ means the first bands until the second to last
\item $'2:4'$ means bands 2,3 and 4
\end{itemize}
\end{itemize}
\item empty by default (all bands are write from the output image)
\end{itemize}
\end{itemize}
......
project(OTBAppSARUtils)
otb_module_impl()
set(OTBAppSARUtils_LINK_LIBS
${OTBSARUtils_LIBRARIES}
${OTBApplicationEngine_LIBRARIES}
)
otb_create_application(
NAME ComputeModulusAndPhase
SOURCES otbComputeModulusAndPhase.cxx
LINK_LIBRARIES ${${otb-module}_LIBRARIES})
/*
* Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
*
* This file is part of Orfeo Toolbox
*
* https://www.orfeo-toolbox.org/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"
#include <otbMultiToMonoChannelExtractROI.h>
#include "itkComplexToPhaseImageFilter.h"
#include "itkComplexToModulusImageFilter.h"
#include <itkMacro.h>
namespace otb
{
// Application class is defined in Wrapper namespace.
namespace Wrapper
{
/** \class ComputeModulusAndPhase
* \brief ComputeModulusAndPhase is an application that
* computes modulus and phase from a complex SAR image.
*
* \ingroup AppSARUtils
*/
class ComputeModulusAndPhase: public Application
{
public:
// Class declaration is followed by ITK public types for the class, the superclass and smart pointers.
typedef ComputeModulusAndPhase Self;
typedef Application Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Standard macro */
itkNewMacro (Self);
itkTypeMacro(ComputeModulusAndPhase, otb::Wrapper::Application);
//typedefs for the application
typedef otb::MultiToMonoChannelExtractROI<typename ComplexFloatVectorImageType::InternalPixelType, typename ComplexFloatImageType::PixelType> ExtractFilterType;
typedef itk::ComplexToModulusImageFilter<ComplexFloatImageType, FloatImageType> ModulusFilterType;
typedef itk::ComplexToPhaseImageFilter<ComplexFloatImageType, FloatImageType> PhaseFilterType;
private:
void DoInit()
{
SetName("ComputeModulusAndPhase");
SetDescription("This application computes the modulus and the phase of a complex SAR image.");
SetDocName("Compute Modulus And Phase");
SetDocLongDescription(
"This application computes the modulus and the phase of a "
"complex SAR image. The input shoud be a single band image with "
"complex pixels."
);
SetDocLimitations("None");
SetDocAuthors("Alexia Mondot (alexia.mondot@c-s.fr) and Mickael Savinaud (mickael.savinaud@c-s.fr)");
SetDocSeeAlso("SARPolarMatrixConvert, SARPolarSynth");
AddDocTag(Tags::SAR);
// Input images
AddParameter(ParameterType_ComplexInputImage, "in", "Input Image");
SetParameterDescription("in", "Input image (complex single band)");
// Outputs
AddParameter(ParameterType_OutputImage, "modulus", "Modulus");
SetParameterDescription("modulus", "Modulus of the input: sqrt(real*real + imag*imag).");
AddParameter(ParameterType_OutputImage, "phase", "Phase");
SetParameterDescription("phase", "Phase of the input: atan2(imag, real).");
AddRAMParameter();
// Doc example parameter settings
SetDocExampleParameterValue("in", "monobandComplexFloat.tif");
SetDocExampleParameterValue("modulus", "modulus.tif");
SetDocExampleParameterValue("phase", "phase.tif");
}
// DoUpdateParameters() is called as soon as a parameter value change.
void DoUpdateParameters()
{
}
// DoExecute() contains the application core.
void DoExecute()
{
m_Modulus = ModulusFilterType::New();
m_Phase = PhaseFilterType::New();
ComplexFloatVectorImageType::Pointer inImage = GetParameterComplexImage("in");
if (inImage->GetNumberOfComponentsPerPixel() != 1)
{
otbAppLogFATAL("Input must be a single band complex image.");
}
// Get first band
m_Extract = ExtractFilterType::New();
m_Extract->SetInput(inImage);
// Compute modulus and phase
m_Modulus->SetInput(m_Extract->GetOutput());
m_Phase->SetInput(m_Extract->GetOutput());
SetParameterOutputImage("modulus", m_Modulus->GetOutput() );
SetParameterOutputImage("phase", m_Phase->GetOutput());
}
ExtractFilterType::Pointer m_Extract;
ModulusFilterType::Pointer m_Modulus;
PhaseFilterType::Pointer m_Phase;
};
} // namespace Wrapper
} // namespace otb
OTB_APPLICATION_EXPORT(otb::Wrapper::ComputeModulusAndPhase)
set(DOCUMENTATION "SAR Utils application.")
otb_module(OTBAppSARUtils
DEPENDS
OTBApplicationEngine
TEST_DEPENDS
OTBTestKernel
OTBCommandLine
DESCRIPTION
"${DOCUMENTATION}"
)
otb_module_test()
#----------- ComputeModulusAndPhase TESTS ----------------
otb_test_application(NAME apTvUtComputeModulusAndPhase_1inputComplex
APP ComputeModulusAndPhase
OPTIONS -in ${INPUTDATA}/monobandComplexFloat.tif
-modulus ${TEMP}/apTvUtMod1inputComplex.tif
-phase ${TEMP}/apTvUtPha1inputComplex.tif
VALID --compare-n-images ${EPSILON_6} 2
${BASELINE}/Mod_monobandComplexFloat.tif
${TEMP}/apTvUtMod1inputComplex.tif
${BASELINE}/Pha_monobandComplexFloat.tif
${TEMP}/apTvUtPha1inputComplex.tif
)
......@@ -100,7 +100,7 @@ private:
AddRAMParameter();
// Doc example parameter settings
SetDocExampleParameterValue("in","avions.tif");
SetDocExampleParameterValue("in","maur_rgb.png");
SetDocExampleParameterValue("inseg","merged.tif");
SetDocExampleParameterValue("out","vector.shp");
SetDocExampleParameterValue("tilesizex","256");
......
......@@ -109,8 +109,8 @@ private:
// Doc example parameter settings
SetDocExampleParameterValue("in", "maur_rgb.png");
SetDocExampleParameterValue("fout", "MeanShift_FilterOutput.tif");
SetDocExampleParameterValue("foutpos", "MeanShift_SpatialOutput.tif");
SetDocExampleParameterValue("fout", "smooth.tif");
SetDocExampleParameterValue("foutpos", "position.tif");
SetDocExampleParameterValue("spatialr", "16");
SetDocExampleParameterValue("ranger", "16");
SetDocExampleParameterValue("thres", "0.1");
......
......@@ -303,7 +303,6 @@ public:
virtual void SetOutputImagePixelType( bool isComplexInternalPixelType,
bool isVectorImage) = 0;
/*-------- This part of the interfaces deals with reading data ----- */
/** Determine the file type. Returns true if this ImageIO can read the
......@@ -421,6 +420,12 @@ public:
*/
const ArrayOfExtensionsType & GetSupportedWriteExtensions() const;
/** Remap band order in an input buffer using band mapping bandList
* This operation is done in-place. The buffer size should enough to
* contain extracted bands before and after mapping. bandList mapping
* between origin components and output components (before any
* conversion)*/
void DoMapBuffer(void* buffer, size_t numberOfPixels, std::vector<unsigned int>& bandList);
protected:
ImageIOBase();
......
......@@ -1269,6 +1269,54 @@ ImageIOBase
return axis;
}
void
ImageIOBase
::DoMapBuffer(void* buffer, size_t numberOfPixels, std::vector<unsigned int>& bandList)
{
size_t componentSize = this->GetComponentSize();
size_t inPixelSize = componentSize * this->GetNumberOfComponents();
size_t outPixelSize = componentSize * bandList.size();
char* inPos = static_cast<char*>(buffer);
char* outPos = static_cast<char*>(buffer);
bool workBackward = (outPixelSize > inPixelSize);
char *pixBuffer = new char[outPixelSize];
memset(pixBuffer, 0, outPixelSize);
if (workBackward)
{
inPos = inPos + numberOfPixels*inPixelSize;
outPos = outPos + numberOfPixels*outPixelSize;
for (size_t n=0 ; n<numberOfPixels ; n++)
{
inPos -= inPixelSize;
outPos -= outPixelSize;
for (unsigned int i=0 ; i < bandList.size() ; i++)
{
memcpy(pixBuffer + i*componentSize, inPos + bandList[i]*componentSize, componentSize);
}
// copy pixBuffer to output
memcpy(outPos, pixBuffer, outPixelSize);
}
}
else
{
for (size_t n=0 ; n<numberOfPixels ; n++)
{
for (unsigned int i=0 ; i < bandList.size() ; i++)
{
memcpy(pixBuffer + i*componentSize, inPos + bandList[i]*componentSize, componentSize);
}
// copy pixBuffer to output
memcpy(outPos, pixBuffer, outPixelSize);
inPos += inPixelSize;
outPos += outPixelSize;
}
}
delete[] pixBuffer;
}
void ImageIOBase::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
......
......@@ -62,6 +62,7 @@ public:
{
m_MuParser.DefineFun("ndvi", Self::NDVI);
m_MuParser.DefineFun("NDVI", Self::NDVI);
m_MuParser.DefineFun("atan2", Self::ATAN2);
#ifdef OTB_MUPARSER_HAS_CXX_LOGICAL_OPERATORS
/* Starting with muParser 2.0.0, logical operators have been
......@@ -208,6 +209,11 @@ private:
}
return (niri-r)/(niri+r);
}
static ValueType ATAN2(ValueType y, ValueType x)
{
return vcl_atan2(y,x);
}
#ifdef OTB_MUPARSER_HAS_CXX_LOGICAL_OPERATORS
static ValueType AND(ValueType left, ValueType right)
......
......@@ -55,6 +55,30 @@ public:
itkGetStringMacro(ExtendedFileName);
itkGetStringMacro(SimpleFileName);
struct GenericBandRange : std::pair<int,int>
{
GenericBandRange() {}
GenericBandRange(int a);
GenericBandRange(const std::pair<int,int>& a);
GenericBandRange(int a,int b);
bool SetString(const std::string& str, size_t start=0 , size_t size=std::string::npos);
void Print(std::ostream& os);
};
/** Decode the string into a list of GenericBandRange, band indexes are
* 1-based. */
std::vector<ExtendedFilenameHelper::GenericBandRange> GetGenericBandRange(const std::string &bandRange) const;
/** Resolve the list of band ranges into real band indexes, according to
* a total number of bands in the image. Note that the output indexes are
* zero-based (0 is the first component) */
bool ResolveBandRange(const std::string &bandRange, const unsigned int &nbBands, std::vector<unsigned int> &output) const;
protected:
ExtendedFilenameHelper() {}
~ExtendedFilenameHelper() ITK_OVERRIDE {}
......
......@@ -35,6 +35,13 @@ namespace otb
* - &resol : resolution factor for jpeg200 files
* - &skipcarto : switch to skip the cartographic information
* - &skipgeom : switch to skip the geometric information
* - &bands : select a band composition different from the input image,
* syntax is bands=r1,r2,r3,...,rn where each ri is a band range
* that can be :
* - a single index (1-based) : '2' means 2nd band, '-1' means last band
* - a range of bands : '3:' means 3rd band until the last one
* ':-2' means the first bands until the second to last
* '2:4' means bands 2,3 and 4
*
* \sa ImageFileReader
*
......@@ -67,6 +74,7 @@ public:
std::pair< bool, bool > skipCarto;
std::pair< bool, bool > skipGeom;
std::pair< bool, bool > skipRpcTag;
std::pair< bool, std::string > bandRange;
std::vector<std::string> optionList;
};
......@@ -86,6 +94,10 @@ public:
bool GetSkipGeom () const;
bool SkipRpcTagIsSet () const;
bool GetSkipRpcTag () const;
std::string GetBandRange () const;
/** Test if band range extended filename is set */
bool BandRangeIsSet () const;
protected:
ExtendedFilenameToReaderOptions();
......
......@@ -72,6 +72,7 @@ public:
std::pair<bool, std::string> streamingSizeMode;
std::pair<bool, double> streamingSizeValue;
std::pair<bool, std::string> box;
std::pair< bool, std::string> bandRange;
std::vector<std::string> optionList;
};
......@@ -91,10 +92,13 @@ public:
std::string GetStreamingSizeMode() const;
bool StreamingSizeValueIsSet() const;
double GetStreamingSizeValue() const;
std::string GetBandRange () const;
bool BoxIsSet() const;
std::string GetBox() const;
/** Test if band range extended filename is set */
bool BandRangeIsSet () const;
protected:
ExtendedFilenameToWriterOptions();
......
......@@ -20,6 +20,8 @@
#include "otbExtendedFilenameHelper.h"
#include "otb_boost_string_header.h"
#include "otbStringUtils.h"
namespace otb
{
......@@ -43,32 +45,31 @@ ExtendedFilenameHelper
{
boost::split(tmp2, tmp1[1], boost::is_any_of("&"), boost::token_compress_on);
for (unsigned int i=0; i<tmp2.size(); i++)
if (tmp2[i].length() >0)
if (!tmp2[i].empty())
{
std::vector<std::string> tmp;
boost::split(tmp, tmp2[i], boost::is_any_of("="), boost::token_compress_on);
if (tmp.size()>1)
{
if (tmp[1].length()>0)
{
if (m_OptionMap[tmp[0]].empty())
{
m_OptionMap[tmp[0]]=tmp[1];
}
else
{
itkWarningMacro("Duplicated option detected: " << tmp[0] << ". Using value " << tmp[1] << ".");
}
}
else
itkGenericExceptionMacro( << "Value for option '" << tmp[0] << "' is not set.");
}
std::vector<std::string> tmp;
boost::split(tmp, tmp2[i], boost::is_any_of("="), boost::token_compress_on);
if (tmp.size()>1)
{
if (!tmp[1].empty())
{
if (m_OptionMap[tmp[0]].empty())
{
m_OptionMap[tmp[0]]=tmp[1];
}
else
{
itkWarningMacro("Duplicated option detected: " << tmp[0] << ". Using value " << tmp[1] << ".");
}
}
else
itkGenericExceptionMacro( << "Value for option '" << tmp[0] << "' is not set.");
}
}
}
}
}
const ExtendedFilenameHelper::OptionMapType &
ExtendedFilenameHelper
::GetOptionMap(void) const
......@@ -76,4 +77,181 @@ ExtendedFilenameHelper
return this->m_OptionMap;
}
/*-------------------- GenericBandRange ----------------------*/
ExtendedFilenameHelper::GenericBandRange
::GenericBandRange(int a)
: std::pair<int,int>(a,a)
{
}
ExtendedFilenameHelper::GenericBandRange
::GenericBandRange(const std::pair<int,int>& a)
: std::pair<int,int>(a)
{
if (a.second>=0 && a.second < a.first)
{
throw std::range_error("Invalid range");
}
}
ExtendedFilenameHelper::GenericBandRange
::GenericBandRange(int a,int b)
: std::pair<int,int>(a,b)
{
if (b>=0 && b < a)
{
throw std::range_error("Invalid range");
}
}
bool
ExtendedFilenameHelper::GenericBandRange
::SetString(const std::string& str, size_t start , size_t size)
{
assert(start < str.size());
bool ret = true;
if (size == 0)
{
first = 0;
second = 0;
return false;
}
size_t end = str.size();
if (size != std::string::npos && (start+size) <= str.size())
{
end = start + size;
}
size_t pos = str.find(':',start);
if (pos != std::string::npos && pos<end)
{
// range of values
if (pos > start)
{
try
{
first = boost::lexical_cast<int>(str.c_str()+start, pos-start);
}
catch(boost::bad_lexical_cast &)
{
ret = false;
}
}
else
{
first = 0;
}
if (end > pos + 1)
{
try