Commit f482a273 authored by Yannick TANGUY's avatar Yannick TANGUY
Browse files

Delete old app, add link to the dataset for unit test in README.md

parent 214af896
......@@ -30,7 +30,8 @@ Enable tests with BUILD_TESTING cmake option. Use `ctest` command to run tests.
For test purpose, the variable `TEST_DATA_ROOT` must be set within cmake.
The archive of testing data can be downloaded here :
A dataset archive is available [here](https://gitlab.orfeo-toolbox.org/remote_modules/image-to-db-registration/-/wikis/Test-data-for-the-remote-module)
## Contributors
Fast line segment detector algorithm :
......
/*
* Copyright (C) 2018 Centre National d'Etudes Spatiales (CNES)
*
* This file is part a Remote Module for Orfeo Toolbox
*
* https://www.orfeo-toolbox.org/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"
#include "otbImage.h"
#include "otbMultiToMonoChannelExtractROI.h"
#include "otbOGRDataSourceWrapper.h"
#include "otbOGRFeatureWrapper.h"
#include "itkWin32Header.h"
#ifdef _WIN
#define OTB_FILE_SEPARATOR '\\'
#else
#define OTB_FILE_SEPARATOR '/'
#endif
#include <vcl_algorithm.h>
extern "C"
{
#include "lsd.h"
}
namespace otb
{
namespace Wrapper
{
class LSDCMLA : public Application
{
public:
typedef LSDCMLA Self;
typedef Application Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
typedef FloatImageType ImageType;
typedef ImageType::InternalPixelType ImagePixelType;
typedef FloatVectorImageType VectorImageType;
typedef VectorImageType::InternalPixelType VectorImagePixelType;
typedef otb::MultiToMonoChannelExtractROI<ImagePixelType,ImagePixelType> ExtractROIFilterType;
typedef itk::ImageRegionConstIterator<ImageType> ImageIteratorType;
itkNewMacro(Self);
itkTypeMacro(Merging, otb::Application);
private:
void DoInit()
{
SetName("LSDCMLA");
SetDescription("Linear-time Line Segment Detector giving subpixel accurate results");
SetDocName("Line Segment Detector (CMLA implementation) : \
Rafael Grompone von Gioi1, Jérémie Jakubowicz, Jean-Michel Morel, Gregory Randall4");
SetDocLongDescription("Linear-time Line Segment Detector giving subpixel accurate results ; \
It is designed to work on any digital image without parameter tuning. \
It controls its own number of false detections: On average, one false alarms is allowed per image. \
The method is based on Burns, Hanson, and Riseman's method, \
and uses an a-contrario validation approach according to Desolneux, Moisan, and Morel's theory. \
The version described here includes some further improvement over the one described in the original article.");
SetDocLimitations("TODO");
SetDocAuthors("Julien Michel");
SetDocSeeAlso("");
AddParameter(ParameterType_InputImage, "in", "Input image");
SetParameterDescription( "in", "The input image." );
AddParameter(ParameterType_OutputFilename, "out", "Output gis file");
SetParameterDescription( "out", "The vector file containing the output lines." );
AddParameter(ParameterType_Float,"scale","Gaussian scaling");
SetParameterDescription("scale","Scale image by Gaussian filter before processing.");
SetDefaultParameterFloat("scale",0.8);
SetMinimumParameterFloatValue("scale",0);
AddParameter(ParameterType_Float,"sigmacoef","Ratio for sigma of gaussian filter");
SetParameterDescription("sigmacoef","Sigma for Gaussian filter is computed as sigma_coef/scale.");
SetDefaultParameterFloat("sigmacoef",0.6);
SetMinimumParameterFloatValue("sigmacoef",0);
AddParameter(ParameterType_Float,"quant","Gradient quantization error");
SetParameterDescription("quant","Bound to quantization error on the gradient norm.");
SetDefaultParameterFloat("quant",2);
SetMinimumParameterFloatValue("quant",0);
AddParameter(ParameterType_Float,"angth","Gradient angle tolerance");
SetParameterDescription("angth","Gradient angle tolerance in degrees.");
SetDefaultParameterFloat("angth",22.5);
SetMinimumParameterFloatValue("angth",0);
AddParameter(ParameterType_Float,"logeps","Detection threshold");
SetParameterDescription("logeps","Detection threshold");
SetDefaultParameterFloat("logeps",0);
AddParameter(ParameterType_Float,"densityth","Minimal density of regions");
SetParameterDescription("densityth","Minimal density of region points in a rectangle to be accepted.");
SetDefaultParameterFloat("densityth",0.7);
SetMinimumParameterFloatValue("densityth",0);
SetMaximumParameterFloatValue("densityth",1);
AddParameter(ParameterType_Int, "nbins", "Number of bins in ordering");
SetParameterDescription("nbins", "Number of bins in ordering of gradient modulus.");
SetDefaultParameterInt("nbins", 1024);
SetMinimumParameterIntValue("nbins", 1);
AddParameter(ParameterType_Int, "tilesizex", "Size of tiles in pixel (X-axis)");
SetParameterDescription("tilesizex", "Size of tiles along the X-axis.");
SetDefaultParameterInt("tilesizex", 500);
SetMinimumParameterIntValue("tilesizex", 1);
AddParameter(ParameterType_Int, "tilesizey", "Size of tiles in pixel (Y-axis)");
SetParameterDescription("tilesizey", "Size of tiles along the Y-axis.");
SetDefaultParameterInt("tilesizey", 500);
SetMinimumParameterIntValue("tilesizey", 1);
}
void DoUpdateParameters()
{
}
void DoExecute()
{
unsigned long sizeTilesX = GetParameterInt("tilesizex");
unsigned long sizeTilesY = GetParameterInt("tilesizey");
//Acquisition of the input image dimensions
VectorImageType::Pointer imageIn = GetParameterImage("in");
imageIn->UpdateOutputInformation();
unsigned long sizeImageX = imageIn->GetLargestPossibleRegion().GetSize()[0];
unsigned long sizeImageY = imageIn->GetLargestPossibleRegion().GetSize()[1];
unsigned int nbTilesX = sizeImageX/sizeTilesX + (sizeImageX%sizeTilesX > 0 ? 1 : 0);
unsigned int nbTilesY = sizeImageY/sizeTilesY + (sizeImageY%sizeTilesY > 0 ? 1 : 0);
double scale = GetParameterFloat("scale");
double sigma_coef = GetParameterFloat("sigmacoef");
double quant = GetParameterFloat("quant");
double ang_th = GetParameterFloat("angth");
double log_eps = GetParameterFloat("logeps");
double density_th = GetParameterFloat("densityth");
unsigned int n_bins = GetParameterInt("nbins");
otb::ogr::DataSource::Pointer ogrDS;
otb::ogr::Layer layer(NULL, false);
OGRSpatialReference oSRS(imageIn->GetProjectionRef().c_str());
std::vector<std::string> options;
ogrDS = otb::ogr::DataSource::New(GetParameterString("out"), otb::ogr::DataSource::Modes::Overwrite);
std::string layername = itksys::SystemTools::GetFilenameName(GetParameterString("out"));
std::string extension = itksys::SystemTools::GetFilenameLastExtension(GetParameterString("out"));
layername = layername.substr(0,layername.size()-extension.size());
layer = ogrDS->CreateLayer(layername, &oSRS, wkbMultiLineString, options);
OGRFieldDefn fieldWidth("width",OFTReal);
OGRFieldDefn fieldP("p",OFTReal);
OGRFieldDefn fieldLogNFA("-log(NFA)",OFTReal);
layer.CreateField(fieldWidth,true);
layer.CreateField(fieldP,true);
layer.CreateField(fieldLogNFA,true);
otbAppLogINFO(<<"Number of tiles: "<<nbTilesX<<" x "<<nbTilesY);
//Sums calculation per label
unsigned int currentProgress = 0;
unsigned long totalNbSegments = 0;
for(unsigned int row = 0; row < nbTilesY; row++)
{
for(unsigned int column = 0; column < nbTilesX; column++)
{
double progress = 100 * static_cast<double>(column+nbTilesX*row)/static_cast<double>(nbTilesX*nbTilesY);
while(progress >= currentProgress)
{
otbAppLogINFO(<<"Progress: "<<currentProgress<<"% ("<<totalNbSegments<<" found so far)");
currentProgress+=10;
}
unsigned long startX = column*sizeTilesX;
unsigned long startY = row*sizeTilesY;
unsigned long sizeX = vcl_min(sizeTilesX,sizeImageX-startX);
unsigned long sizeY = vcl_min(sizeTilesY,sizeImageY-startY);
//Tiles extraction of the segmented image
ExtractROIFilterType::Pointer imageROI = ExtractROIFilterType::New();
imageROI->SetInput(imageIn);
imageROI->SetStartX(startX);
imageROI->SetStartY(startY);
imageROI->SetSizeX(sizeX);
imageROI->SetSizeY(sizeY);
imageROI->SetChannel(1);
imageROI->Update();
double * image = new double[(size_t)(sizeX*sizeY)];
ImageIteratorType it(imageROI->GetOutput(),imageROI->GetOutput()->GetLargestPossibleRegion());
unsigned long idx = 0;
for(it.GoToBegin();!it.IsAtEnd() && idx < sizeX*sizeY;++it,++idx)
{
image[idx] = it.Get();
}
int n = 0;
int regXNotUsed = 0;
int regYNotUsed = 0;
double * segs = LineSegmentDetection(&n, image, sizeX, sizeY,
scale, sigma_coef, quant,
ang_th, log_eps, density_th,
n_bins,NULL,&regXNotUsed,&regYNotUsed);
totalNbSegments+=n;
for(unsigned int idx = 0; idx < n;++idx)
{
OGRMultiLineString newMultiLineString;
OGRLineString newLineString;
itk::ContinuousIndex<double,2> a,b;
a[0] = segs[idx * 7];
a[1] = segs[idx * 7 + 1];
b[0] = segs[idx * 7 + 2];
b[1] = segs[idx * 7 + 3];
double width = segs[idx * 7 + 4];
double p = segs[idx * 7 + 5];
double lognfa = segs[idx * 7 + 6];
ImageType::PointType pa, pb;
imageROI->GetOutput()->TransformContinuousIndexToPhysicalPoint(a,pa);
imageROI->GetOutput()->TransformContinuousIndexToPhysicalPoint(b,pb);
// We assume isotropic spacing here
width *= vcl_abs(imageROI->GetOutput()->GetSpacing()[0]);
newLineString.addPoint(pa[0],pa[1],0);
newLineString.addPoint(pb[0],pb[1],0);
newMultiLineString.addGeometry(&newLineString);
otb::ogr::Feature newFeature(layer.GetLayerDefn());
newFeature.SetGeometry(&newMultiLineString);
newFeature.ogr().SetField("Width",width);
newFeature.ogr().SetField("-log(NFA)",lognfa);
newFeature.ogr().SetField("p",p);
layer.CreateFeature(newFeature);
}
layer.ogr().CommitTransaction();
// Release memory
delete [] image;
free( (void *) segs );
}
}
ogrDS->SyncToDisk();
otbAppLogINFO(<<"Progress: 100% ("<<totalNbSegments<<" found)");
}
};
}
}
OTB_APPLICATION_EXPORT(otb::Wrapper::LSDCMLA)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment