For the case of older medium-resolution imagery over rugged terrain, it is still interesting being able to apply a simple polynomial model but considering x,y,z coordinates as described in [1]. An important application would be the case of ASTER imagery, which is still very appreciated in Earth Sciences. I tried to use GenerateRPCSensorModel in the past, but the results were very bad (see the end of the discussion in the older list [2]).
Perhaps just letting the user to set denominators to 1 in GenerateRPCSensorModel could be a way?
[1] Pala, V., and X. Pons. 1995. “Incorporation of Relief in Polynomial-Based Geometric Correction.” Photogrametrics Engineering & Remote Sensing 61: 935–44. 01_Incorporation_of_Relief_in_Polynomial-Based_Geometric_Correction.pdf
Sorry but this story is too old. We prefer to close it but feel free to open an other one (with more details if possible) or contribute a Merge Request.
Warping should not be part of FineRegistration
application as we already have a GridBasedResampling
application that does the job.
Won't do, we close this issue.
Too old, we close this issue
I have an OTB application tested with the test driver that freezes in MPI_Finalize()
when an exception is thrown from the MyOTBApp::DoExecute()
function.
The test is launched with:
otbTestDriver "Execute" "/path/to/bin/otbApplicationLauncherCommandLine" "MyOtbApp" "the" "parameters" "-testenv"
If no exception is thrown, MPI_Finalize()
correctly returns.
If an (ITK) exception interrupts TheApp::DoExecute()
the process hangs in
(gdb) bt
#0 0x00007f6af1bee56d in nanosleep () from /lib64/libc.so.6
#1 0x00007f6af1c1f404 in usleep () from /lib64/libc.so.6
#2 0x00007f6af24da7cf in ompi_mpi_finalize () from /path/to/lib/libmpi.so.20
#3 0x00007f6af6075b85 in otb::MPIConfig::terminate() () from /other/path/to/otb/lib/libOTBMPIConfig-6.7.so.1
I haven't been able to understand what (pending?) message (or whatever) is preventing MPI_FInalize()
to return. I could execute MPI_abort()
just before the return -1
(BTW why isn't it return result;
?) in otbTestMain.h
which shouldn't be a big issue given we are in a failing test. But is it the right approach? (I'm not a MPI expert)
I've loaded current OTB (6.7?) modules on HAL: otb/develop-python3 and otb-depends/develop-python3
The use of the MPI singleton seems convoluted in the test. I would have worked with something like
// mpi_helper.h
namespace mpi {
class Singleton : boost::noncopyable
{
public:
static Singleton& create(int argc, char** argv) {
assert(! ms_instance);
ms_instance = make_unique<Singleton>(argc, argv);
return *ms_instance;
}
static Singleton& instance() {
assert(ms_instance);
return * ms_instance;
}
Singleton(int argc, char** argv) { .... }
~Singleton() { mpi_abort or mpi_terminate depending on exceptions and so on...}
static void abort() { ... } // needs to clear the singleton as weel
void barrier() { ... }
// do we really need an explicit terminate? if yes, it should be static as well to clear the singleton
private:
std::unique_ptr<Singleton> ms_instance;
};
}
// otbTestDriver.h
...
int main(int argc, char** argv) {
#if defined(USE_MPI)
mpi::Singleton::create(argc, argv);
#endif
...
if (result != EXIT_SUCCESS) {
#if defined(USE_MPI)
mpi::Singleton::abort(result)
#else
return result;
#endif
}
....
} // no need to explicitly call terminate
Won't do, we close that issue (and probably abandon MPI support)
The goal of this issue is to create a Conda environment that allows to use OTB through Conda.
Current status:
We have a recipe for OTB dependencies (either don't exist in the conda forge, or were unusable), and OTB itself. But right now this is not built on the new CI and only works on linux. (see @dyoussef's comment below)
Proposed TODO:
Closed, we give up conda support for now
Too old, we close this issue
otb::TestHelper::RegressionTestOgrFile()
[1]:
N.B.: Subsequent OTB functions called by this code should be reviewed as well.
File: otbTestHelper.patch
diff --git a/Modules/IO/TestKernel/src/otbTestHelper.cxx b/Modules/IO/TestKernel/src/otbTestHelper.cxx
index 95128d65db..af6b5edfca 100644
--- a/Modules/IO/TestKernel/src/otbTestHelper.cxx
+++ b/Modules/IO/TestKernel/src/otbTestHelper.cxx
@@ -1718,6 +1718,8 @@ std::map<std::string, int> TestHelper::RegressionTestBaselines(char *baselineFil
int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *baselineOgrFilename,
const double toleranceDiffValue) const
{
+ // Use assertions on input parameters.
+
const char *ref_pszDataSource = baselineOgrFilename;
const char *test_pszDataSource = testOgrFilename;
//const char *ref_pszWHERE = NULL;
@@ -1727,6 +1729,12 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b
/* -------------------------------------------------------------------- */
/* Open data source. */
/* -------------------------------------------------------------------- */
+ //
+ // 1. Should be replaced by read-only otb::ogr::DataSource (in
+ // Adapters/GdalAdapters/include/otbOGRDataSourceWrappers.h)
+ // providing exception-safety (against memory-leaks).
+ //
+ // {
GDALDataset *ref_poDS = nullptr;
GDALDriver * ref_poDriver = nullptr;
//OGRGeometry * ref_poSpatialFilter = NULL;
@@ -1776,43 +1784,66 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b
std::cout << "Had to open TEST data source read-only."<<std::endl;
}
}
+ // } (1)
/* -------------------------------------------------------------------- */
/* Report failure */
/* -------------------------------------------------------------------- */
+ //
+ // 2. Can be replaced by try/catch if (1)
+ //
+ // {
if (ref_poDS == nullptr)
{
-
if (m_ReportErrors)
{
std::cout << "FAILURE:\n" "Unable to open REF datasource `" << ref_pszDataSource << "' with the following drivers." << std::endl;
+ // 2.1. Should be factorized into private function
+ // {
std::vector<std::string> drivers = ogr::GetAvailableDriversAsStringVector();
for (std::vector<std::string>::const_iterator it = drivers.begin();it!=drivers.end();++it)
{
std::cout << " -> " << *it << std::endl;
}
+ // } (2.1)
}
+ // Memory-leak of GDALDataset instances in case of error, see (1)
+ // {
return (1);
+ // }
}
+ //
+ // } (2)
ref_poDriver = ref_poDS->GetDriver();
CPLAssert(ref_poDriver != NULL);
+ //
+ // 2. Can be replaced by try/catch if (1)
+ //
+ // {
if (test_poDS == nullptr)
{
if (m_ReportErrors)
{
std::cout << "FAILURE:\n""Unable to open TEST datasource `" << test_pszDataSource << "' with the following drivers." << std::endl;
+ // 2.1. Should be factorized into private function
+ // {
std::vector<std::string> drivers = ogr::GetAvailableDriversAsStringVector();
for (std::vector<std::string>::const_iterator it = drivers.begin();it!=drivers.end();++it)
{
std::cout << " -> " << *it << std::endl;
}
+ // } (2.1)
}
+ // Memory-leak of GDALDataset instances in case of error, see (1)
+ // {
return (1);
+ // }
}
+ // } (2)
test_poDriver = test_poDS->GetDriver();
CPLAssert(test_poDriver != NULL);
@@ -1823,11 +1854,21 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b
// TODO: Improve this check as it will stop as soon as one of the
// list ends (i.e. it does not guarantee that all files are present)
+ //
+ // 3. This part is debatable and might be
+ // removed/improved/optimized: it checks that all auxiliary files
+ // are the same for both ref and test filenames thus making the
+ // hypothesis that both basenames are the same which is not
+ // necessarily needed.
+ //
+ // {
std::vector<std::string> refFileList = otb::ogr::GetFileListAsStringVector(ref_poDS);
std::vector<std::string> testFileList = otb::ogr::GetFileListAsStringVector(test_poDS);
unsigned int fileId = 0;
+ // See TOTO above: maybe a simple
+ // refFileList.size()==testFileList.size() would be enough.
while (fileId < refFileList.size() && fileId < testFileList.size())
{
std::string strRefName(refFileList[fileId]);
@@ -1843,7 +1884,7 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b
}
++fileId;
}
-
+ // } (3)
/* -------------------------------------------------------------------- */
/* Process each data source layer. */
/* -------------------------------------------------------------------- */
@@ -1851,6 +1892,8 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b
for (int iLayer = 0; iLayer < ref_poDS->GetLayerCount(); ++iLayer)
{
+ // 4. See (1) and use safe OTB OGR wrappers.
+ // {
OGRLayer *ref_poLayer = ref_poDS->GetLayer(iLayer);
OGRLayer *test_poLayer = test_poDS->GetLayer(iLayer);
@@ -1859,7 +1902,10 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b
if (m_ReportErrors)
std::cout << "FAILURE: Couldn't fetch advertised layer " << iLayer <<
" for REF data source" << std::endl;
+ // 4.1. Memory-leak of OGRLayer if error
+ // {
return (1);
+ // }
}
if (test_poLayer == nullptr)
{
@@ -1868,6 +1914,7 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b
" for REF data source" << std::endl;
return (1);
}
+ // } (4)
//Check Layer inforamtion
ogrReportOnLayer(ref_poLayer, nullptr, nullptr, test_poLayer, nullptr, nullptr, nbdiff);
@@ -1875,8 +1922,11 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b
//If no difference, check the feature
if (nbdiff == 0)
{
+ // 5. Use safe OTB OGR wrappers, see (1) and (4)
+ // {
OGRFeature * ref_poFeature = nullptr;
OGRFeature * test_poFeature = nullptr;
+ // }
std::string basefilename(test_pszDataSource);
int nbFeature(0);
std::stringstream oss2;
@@ -1890,29 +1940,48 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b
oss.str("");
oss << nbFeature;
+ // 5.1. Should be factorized in private utilitary function.
+ // {
std::string ref_filename = basefilename + "_temporary_layer_" + oss2.str() + "_feature_" + oss.str()
+ "_ref.txt";
std::string test_filename = basefilename + "_temporary_layer_" + oss2.str() + "_feature_" + oss.str()
+ "_test.txt";
+ // }
+
+ // 5.2. Should be factorized in private utilitary
+ // sub-function using C++ file streams instead of C file API.
+ // {
FILE *ref_f(nullptr);
ref_f = fopen(ref_filename.c_str(), "w");
if (ref_f == nullptr)
{
+ // 5.2.1 Memory-leak of OGRFeature, if error
+ // {
itkGenericExceptionMacro(<< "Impossible to create ASCII file <" << ref_filename << ">.");
+ // } (5.2.1)
}
DumpOGRFeature(ref_f, ref_poFeature);
OGRFeature::DestroyFeature( ref_poFeature );
fclose(ref_f);
+ // } (5.2)
+ // 5.2. Should be factorized in private utilitary
+ // sub-function using C++ file stream API instead of C file
+ // API.
+ // {
FILE *test_f(nullptr);
test_f = fopen(test_filename.c_str(), "w");
if (test_f == nullptr)
{
+ // 5.2.1 Memory-leak of OGRFeature, if error
+ // {
itkGenericExceptionMacro(<< "Impossible to create ASCII file <" << test_filename << ">.");
+ // } (5.2.1)
}
DumpOGRFeature(test_f, test_poFeature);
OGRFeature::DestroyFeature( test_poFeature );
fclose(test_f);
+ // } (5.2)
//Check ASCII comparison
std::vector<std::string> ignoredLines;
N.A.
Any.
This is an old (!!) issue, but we think it should be implemented by future versions of OTB. At least the documentation should explain how different applications can handle no data.
As contrast through histogram equalization is often too intense and heavily non-linear, I would add an option for a simple local linear stretching.
Too old, we close this story.
Maybe I am missing something, but why is there a (short) hardcoded list of OGR drivers in VectorDataIO? It blocks usage of other drivers which work just fine. For example GPKG:
diff --git a/Modules/IO/IOGDAL/src/otbOGRVectorDataIO.cxx b/Modules/IO/IOGDAL/src/otbOGRVectorDataIO.cxx
index f47b192d7e..b3b7ef31c2 100644
--- a/Modules/IO/IOGDAL/src/otbOGRVectorDataIO.cxx
+++ b/Modules/IO/IOGDAL/src/otbOGRVectorDataIO.cxx
@@ -329,6 +329,7 @@ OGRVectorDataIO::GetOGRDriverName(std::string name) const
else if (extension == ".SQLITE") driverOGR = "SQLite";
else if (extension==".KML") driverOGR="KML";
else if (extension == ".GMT") driverOGR = "OGR_GMT";
+ else if (extension == ".GPKG") driverOGR = "GPKG";
else driverOGR = "NOT-FOUND";
}
To test if a file can be read it would be better to ask the OGR api, no? Compiling with the above diff makes OTB able to write .gpkg
files.
Good idea to rely on OGR API but as it works fine now with most used drivers, we close this issue.
Doxygen
Some classes in OTB are not available in doxygen main class index. See for instance LAIFromNDVILogarithmic
:
Can not be found in: https://www.orfeo-toolbox.org//doxygen/classes.html
It is however available here: https://www.orfeo-toolbox.org//doxygen/classotb_1_1Functor_1_1LAIFromNDVILogarithmic.html
Won't do.
This subject will be studied again with latest OTB 9.0, based on GDAL 3.8.