From d51312255b0f8f1f296ae8df7be2d3acbe1f3709 Mon Sep 17 00:00:00 2001 From: Luc Hermitte Date: Thu, 13 Aug 2020 18:40:42 +0200 Subject: [PATCH 01/16] Integrate S1Tiling support apps as official remote module --- .../S1TilingSupportApplications.remote.cmake | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 Modules/Remote/S1TilingSupportApplications.remote.cmake diff --git a/Modules/Remote/S1TilingSupportApplications.remote.cmake b/Modules/Remote/S1TilingSupportApplications.remote.cmake new file mode 100644 index 0000000000..9f703315a1 --- /dev/null +++ b/Modules/Remote/S1TilingSupportApplications.remote.cmake @@ -0,0 +1,31 @@ +# +# Copyright(C) 2005-2020 Centre National d'Etudes Spatiales(CNES) +# +# This file is part of S1Tiling remote module for 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. +# +# Contact: Thierry Koleck + + +otb_fetch_module(S1TilingSupportApplications + "Speckle filtering of a time-serie of SAR images using the multichanel Quegan-like filter +A more detailed description can be found on the project website: +https://gitlab.orfeo-toolbox.org/s1-tiling/s1tilingsupportapplications +" + GIT_REPOSITORY https://gitlab.orfeo-toolbox.org/s1-tiling/s1tilingsupportapplications + # Commit on master branch + GIT_TAG master +) -- GitLab From bb7f40280148ff5c708dba74f252eac58056e4c3 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Fri, 14 Aug 2020 10:09:52 +0200 Subject: [PATCH 02/16] Update .mailmap with new email address for Luc --- .mailmap | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index 646d37da89..5e700782f0 100644 --- a/.mailmap +++ b/.mailmap @@ -57,7 +57,9 @@ Julien Michel Julien Michel Julien Osman Laurențiu Nicola Laurentiu Nicola Laurențiu Nicola Laurențiu Nicola -Luc Hermitte Luc Hermitte +Luc Hermitte +Luc Hermitte Luc Hermitte +Luc Hermitte Luc Hermitte Ludovic Hussonnois Manuel Grizonnet Manuel Grizonnet Grizonnet Manuel -- GitLab From b50f0a8c59de104cd0db1fa985afd2d44454a8fe Mon Sep 17 00:00:00 2001 From: Luc Hermitte Date: Wed, 19 Aug 2020 15:21:41 +0200 Subject: [PATCH 03/16] COM: Fix copyright header for S1TilingApps remote module --- Modules/Remote/S1TilingSupportApplications.remote.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Remote/S1TilingSupportApplications.remote.cmake b/Modules/Remote/S1TilingSupportApplications.remote.cmake index 9f703315a1..9be4b33b59 100644 --- a/Modules/Remote/S1TilingSupportApplications.remote.cmake +++ b/Modules/Remote/S1TilingSupportApplications.remote.cmake @@ -1,7 +1,7 @@ # # Copyright(C) 2005-2020 Centre National d'Etudes Spatiales(CNES) # -# This file is part of S1Tiling remote module for Orfeo Toolbox +# This file is part of Orfeo Toolbox # # https: //www.orfeo-toolbox.org/ # -- GitLab From e56355fe8df8b318c8a3aa2a0728e01639d68116 Mon Sep 17 00:00:00 2001 From: Luc Hermitte Date: Thu, 20 Aug 2020 11:15:45 +0200 Subject: [PATCH 04/16] COM: Fix copyright header for S1TilingApps remote module --- Modules/Remote/S1TilingSupportApplications.remote.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/Remote/S1TilingSupportApplications.remote.cmake b/Modules/Remote/S1TilingSupportApplications.remote.cmake index 9be4b33b59..402f984e7b 100644 --- a/Modules/Remote/S1TilingSupportApplications.remote.cmake +++ b/Modules/Remote/S1TilingSupportApplications.remote.cmake @@ -1,15 +1,15 @@ # -# Copyright(C) 2005-2020 Centre National d'Etudes Spatiales(CNES) +# Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES) # # This file is part of Orfeo Toolbox # -# https: //www.orfeo-toolbox.org/ +# https://www.orfeo-toolbox.org/ # -# Licensed under the Apache License, Version 2.0(the "License"); +# 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 +# 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, -- GitLab From bd044664d54c150eb0a47c5e51f7f932d761fc55 Mon Sep 17 00:00:00 2001 From: Luc Hermitte Date: Mon, 31 Aug 2020 17:14:31 +0200 Subject: [PATCH 05/16] ENH: Contribute 2 S1TilingApps to OTB --- .../AppImageUtils/app/CMakeLists.txt | 10 + .../AppImageUtils/app/otbClampROI.cxx | 129 ++++++ .../AppImageUtils/app/otbSynthetize.cxx | 134 ++++++ Modules/Core/Common/include/otbInterval.h | 99 +++++ Modules/Core/Common/include/otbLogHelpers.h | 64 +++ Modules/Core/Common/include/otbSpan.h | 251 +++++++++++ Modules/Core/Common/include/otbZipIterator.h | 419 ++++++++++++++++++ .../Functor/include/otbSynthetizeFilter.h | 239 ++++++++++ .../include/otbClampROIFilter.h | 154 +++++++ .../include/otbClampROIFilter.hxx | 216 +++++++++ .../S1TilingSupportApplications.remote.cmake | 2 +- 11 files changed, 1716 insertions(+), 1 deletion(-) create mode 100644 Modules/Applications/AppImageUtils/app/otbClampROI.cxx create mode 100644 Modules/Applications/AppImageUtils/app/otbSynthetize.cxx create mode 100644 Modules/Core/Common/include/otbInterval.h create mode 100644 Modules/Core/Common/include/otbLogHelpers.h create mode 100644 Modules/Core/Common/include/otbSpan.h create mode 100644 Modules/Core/Common/include/otbZipIterator.h create mode 100644 Modules/Core/Functor/include/otbSynthetizeFilter.h create mode 100644 Modules/Filtering/ImageManipulation/include/otbClampROIFilter.h create mode 100644 Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx diff --git a/Modules/Applications/AppImageUtils/app/CMakeLists.txt b/Modules/Applications/AppImageUtils/app/CMakeLists.txt index 8f2981b694..f1b82f4031 100644 --- a/Modules/Applications/AppImageUtils/app/CMakeLists.txt +++ b/Modules/Applications/AppImageUtils/app/CMakeLists.txt @@ -92,3 +92,13 @@ OTB_CREATE_APPLICATION( NAME Mosaic SOURCES otbMosaic.cxx LINK_LIBRARIES ${${otb-module}_LIBRARIES}) + +OTB_CREATE_APPLICATION( + NAME ClampROI + SOURCES otbClampROI.cxx + LINK_LIBRARIES ${${otb-module}_LIBRARIES}) + +OTB_CREATE_APPLICATION( + NAME Synthetize + SOURCES otbSynthetize.cxx + LINK_LIBRARIES ${${otb-module}_LIBRARIES}) diff --git a/Modules/Applications/AppImageUtils/app/otbClampROI.cxx b/Modules/Applications/AppImageUtils/app/otbClampROI.cxx new file mode 100644 index 0000000000..0d49ca2433 --- /dev/null +++ b/Modules/Applications/AppImageUtils/app/otbClampROI.cxx @@ -0,0 +1,129 @@ +/* + * Copyright(C) 2005-2020 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 "otbClampROIFilter.h" +#include "otbWrapperApplication.h" +#include "otbWrapperApplicationFactory.h" + +namespace otb +{ +namespace Wrapper +{ + +/** + * Application that fills margins to 0. + * + * This application is similar to ExtractROI with the difference the margin is + * kept, and filled with 0. + * + * This application is used to implement the _cut_ processing in S1Tiling + * chain. + * + * \author Luc Hermitte (CS Group) + * \copyright CNES + */ +class ClampROI : public Application +{ +public: + using Self = ClampROI; + using Pointer = itk::SmartPointer; + + itkNewMacro(Self); + itkTypeMacro(ClampROI, otb::Wrapper::Application); + +private: + void DoInit() override + { + SetName("ClampROI"); + + SetDescription("This is the ClampROI application, version X.X.X"); + SetDocLongDescription( + "This application is similar to ExtractROI in the sense it extracts a Region of Interrest.\n" + "However, the region outside of the ROI isn't trimmed, but set to 0.\n" + "\n" + "The filter set lines of index < threshold.y, and of index >= threshold.y to 0\n" + "The filter set columns of index < threshold.x, and of index >= threshold.x to 0"); + + SetDocLimitations("This application only works on scalar (and complex) images."); + SetDocAuthors("Luc Hermitte (CS Group)"); + SetDocSeeAlso("ManageNoData, ExtractROI"); + AddDocTag("otb::Wrapper::Tags::Manip"); + + AddParameter(ParameterType_InputImage, "in", "Input image"); + SetParameterDescription("in", "Scalar Input image"); + + AddParameter(ParameterType_OutputImage, "out", "Output Image"); + SetParameterDescription("out", "Scalar Output image"); + + AddParameter(ParameterType_Group, "threshold", "threshold group"); + AddParameter(ParameterType_Group, "threshold.y", "threshold group"); + MandatoryOff("threshold"); + MandatoryOff("threshold.y"); + AddParameter(ParameterType_Int, "threshold.x", "Column index threshold"); + SetParameterDescription("threshold.x", "Column index threshold"); + SetDefaultParameterInt("threshold.x", 0); + + AddParameter(ParameterType_Int, "threshold.y.start", "Top line index threshold"); + SetParameterDescription("threshold.y.start", "Top line index threshold"); + SetDefaultParameterInt("threshold.y.start", 0); + + AddParameter(ParameterType_Int, "threshold.y.end", "Bottom line index threshold"); + SetParameterDescription("threshold.y.end", "Bottom line index threshold"); + SetDefaultParameterInt("threshold.y.end", 0); + + AddRAMParameter(); + } + + void DoUpdateParameters() override + {} + + void DoExecute() override + { + auto const thrX = GetParameterInt("threshold.x"); + auto const thrYtop = GetParameterInt("threshold.y.start"); + auto const thrYbot = GetParameterInt("threshold.y.end"); + if (thrX < 0) + itkExceptionMacro("The column threshold is expected to be positive"); + if (thrYtop < 0) + itkExceptionMacro("The top line threshold is expected to be positive"); + if (thrYbot < 0) + itkExceptionMacro("The bottom line threshold is expected to be positive"); + if (thrX == 0 && thrYtop == 0 && thrYbot == 0) + itkExceptionMacro("Don't use ClampROI to clamp nothing!"); + + auto filter = ClampROIFilter::New(); + assert(thrX >= 0); + assert(thrYtop >= 0); + assert(thrYbot >= 0); + filter->SetThresholdX(thrX); + filter->SetThresholdYtop(thrYtop); + filter->SetThresholdYbot(thrYbot); + filter->SetInput(GetParameterFloatImage("in")); + + SetParameterOutputImage("out", filter->GetOutput()); + RegisterPipeline(); + } + +}; + +} // otb::Wrapper namespace +} // otb namespace + +OTB_APPLICATION_EXPORT(otb::Wrapper::ClampROI) diff --git a/Modules/Applications/AppImageUtils/app/otbSynthetize.cxx b/Modules/Applications/AppImageUtils/app/otbSynthetize.cxx new file mode 100644 index 0000000000..fa77fdcba8 --- /dev/null +++ b/Modules/Applications/AppImageUtils/app/otbSynthetize.cxx @@ -0,0 +1,134 @@ +/* + * Copyright(C) 2005-2020 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 "otbSynthetizeFilter.h" +#include "otbWrapperApplication.h" +#include "otbWrapperApplicationFactory.h" +#include "otbImageFileReader.h" +#include + +namespace otb +{ +namespace Wrapper +{ + +/** + * This application synthetizes/reduces multiple inputs into a single one. + * In that particular case, for each output pixel, this application will + * consider the corresponding pixels from all the input images, and keep the + * first one that isn't equal to 0. + * + * This application is used to implement the _concatenate_ processing in + * S1Tiling chain. + * + * \author Luc Hermitte (CS Group) + * \copyright CNES + * \todo find a better name for the application. Alas `otbConcatenate` is + * already used... + */ +class Synthetize : public Application +{ +public: + using Self = Synthetize; + using Pointer = itk::SmartPointer; + + itkNewMacro(Self); + itkTypeMacro(Synthetize, otb::Wrapper::Application); + +private: + using ReaderType = otb::ImageFileReader; + + void DoInit() override + { + SetName("Synthetize"); + + SetDescription("This is the Synthetize application, version X.X.X"); + SetDocLongDescription("Concatenate a list of images of the same size into a single single-channel image.\n\ + It keeps the first non-null pixel value found in the input list."); + + SetDocLimitations("This application will break incoming pipelines."); + SetDocAuthors("Luc Hermitte (CS Group)"); + SetDocSeeAlso(""); + AddDocTag("otb::Wrapper::Tags::Manip"); + + AddParameter(ParameterType_StringList, "il", "Input images list"); + SetParameterDescription("il", "Input image list"); + + AddParameter(ParameterType_OutputImage, "out", "Output Image"); + SetParameterDescription("out","Output image."); + + AddRAMParameter(); + } + + void DoUpdateParameters() override + {} + + void DoExecute() override + { + // Get the input image list + auto inNameList = GetParameterStringList("il"); + + // checking the input images list validity + auto const nbImages = inNameList.size(); + + if (nbImages == 0) + { + itkExceptionMacro("No input Image set...; please set at least one input image"); + } + + auto functor = [](auto input) { + assert(!input.empty()); + auto const wh = std::find_if( + input.begin(), input.end()-1, + [](auto v){ return v != 0;}); + return *wh; + }; + auto filter = MakeSynthetizeFilter(functor); + + for (unsigned int i = 0; i < nbImages; i++) + { + // Given the explicit use of a Reader, this application cannot be used in + // a in-memory pipeline + auto reader = ReaderType::New(); + // currentImage->SetExtendedFileName(inNameList[i]); + reader->SetFileName(inNameList[i]); + auto currentImage = reader->GetOutput(); + currentImage->UpdateOutputInformation(); + + otbAppLogINFO(<< "Image #" << i + 1 << " has " << currentImage->GetNumberOfComponentsPerPixel() << " components"); + + filter->SetInput(i, currentImage); + m_Cache.insert(reader); + } + + SetParameterOutputImage("out", filter->GetOutput()); + RegisterPipeline(); // TODO: check!! + } + + // Needed to register the inputs handled manually + // and not with a VectorImageList through GetParameterImageList + std::set m_Cache; +}; + +} // otb::Wrapper namespace +} // otb namespace + +OTB_APPLICATION_EXPORT(otb::Wrapper::Synthetize) diff --git a/Modules/Core/Common/include/otbInterval.h b/Modules/Core/Common/include/otbInterval.h new file mode 100644 index 0000000000..5e6ce66b9b --- /dev/null +++ b/Modules/Core/Common/include/otbInterval.h @@ -0,0 +1,99 @@ +/* + * Copyright(C) 2005-2020 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. + */ + + +#ifndef otbInterval_h +#define otbInterval_h + +#include "itkIntTypes.h" +#include +#include + +namespace otb +{ +/** Simplified index interval. + * Inspired by `boost::numeric::interval`. + * + * \invariant Can be empty. + * \invariant lower <= upper + * \author Luc Hermitte (CS Group) + * \copyright CNES + * \ingroup OTBCommon + */ +class Interval +{ +public: + using IndexType = itk::IndexValueType; + using SizeType = itk::SizeValueType; + + /** Init constructor from the pair of its extremities. */ + constexpr Interval(IndexType l, IndexType u) noexcept + : m_lower(l), m_upper(u) + { + assert(l <= u); + } + + /** Alternate factory function from a position and a length. */ + static constexpr Interval OfLength(IndexType low, SizeType len) noexcept{ + return Interval{low, IndexType(low+len)}; + } + + constexpr SizeType size() const noexcept + { return m_upper - m_lower; } + + constexpr bool empty() const noexcept + { return m_lower == m_upper; } + + constexpr IndexType lower() const noexcept + { return m_lower; } + + constexpr IndexType upper() const noexcept + { return m_upper; } + + /** Computes the intersection between two interals. + * @return their intersection + * @return {0,0} if theyr don't intersect. + * + * @note this function is an hidden friend + */ + friend constexpr Interval intersect( + Interval const& lhs, Interval const& rhs) noexcept + { + auto const low = std::max(lhs.lower(), rhs.lower()); + auto const upp = std::min(lhs.upper(), rhs.upper()); + + return low <= upp ? Interval{low, upp} : Interval{0,0}; + } + + /** Stream inserter for intervals. + * @note this function is an hidden friend + */ + friend std::ostream & operator<<(std::ostream & os, Interval const& v) + { + return os << '[' << v.lower() << ".." << v.upper() << '['; + } + +private: + IndexType m_lower; + IndexType m_upper; +}; +} // otb namespace + +#endif // otbInterval_h diff --git a/Modules/Core/Common/include/otbLogHelpers.h b/Modules/Core/Common/include/otbLogHelpers.h new file mode 100644 index 0000000000..98239512b3 --- /dev/null +++ b/Modules/Core/Common/include/otbLogHelpers.h @@ -0,0 +1,64 @@ +/* + * Copyright(C) 2005-2020 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. + */ + + +#ifndef otbLogHelpers_h +#define otbLogHelpers_h + +#include "itkImageRegion.h" +#include + +namespace otb +{ + +/** Helper class to log region in a more human readable way: + * e.g. + * \code + x ∈ [0..42[, y ∈ [12..24[, size=42x12 @(0, 12) + * \endcode + * \author Luc Hermitte (CS Group) + * \copyright CNES + * \ingroup OTBCommon + */ +struct NeatRegionLogger +{ + using RegionType = itk::ImageRegion<2u>; + NeatRegionLogger(RegionType const& region) : m_region(region) {} + + friend std::ostream & operator<<(std::ostream & os, NeatRegionLogger const& r) + { + auto const& size = r.m_region.GetSize(); + auto const& idx = r.m_region.GetIndex(); + auto const idx_x1 = idx[0]; + int const idx_x2 = idx[0] + size[0]; + int const idx_y1 = idx[1]; + auto const idx_y2 = idx[1] + size[1]; + os + << "x ∈ ["< +#include +#include + +namespace otb +{ + +/** Span class inspired by C++20 standard. + * \todo fix RW / RO interface + * \author Luc Hermitte (CS Group) + * \copyright CNES + * \ingroup OTBCommon + */ +template struct Span +{ + /**\name Typedefs */ + //@{ + using element_type = T; + using value_type = std::remove_cv_t; + using index_type = std::size_t; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using const_pointer = T const*; + using reference = T&; + using const_reference = T const&; + using iterator = T*; + using const_iterator = T const*; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + //@} + + /**\name Constructors */ + //@{ + constexpr Span() noexcept = default; + constexpr Span(pointer ptr, index_type count) noexcept + : m_buffer(ptr), m_size(count) + { + assert(! (!ptr) xor (!count)); + } + constexpr Span(pointer first, pointer last) noexcept + : Span(first, last - first) + { + assert(! (!first) xor (!last)); + assert(first <= last); + } + template constexpr Span(element_type (&arr)[N]) noexcept + : Span(arr, N) + {} + + /** Converting constructor from a contiguous container. + * \pre The Container shall be contiguous + * \warning The lifetime of the span shall not exceed the one of the container. + * Be sure to not store the span locally, and initialize it from a rvalue. + * The use case where a span is initialize from a rvalue shall be restricted + * to function parameters. + * \code + * std::vector f(); + * void g(Span sp); + * ... + * Span sp(f()); // NO!!! Use after release + * g(f()); // OK!! + * \endcode + * + * \todo static_assert the container is contiguous + */ + template constexpr Span(Container&& cont) noexcept + : Span(&cont[0], cont.size()) + { + // We cannot use op[] which has an assertion sometimes. + // assert(&const[size()] == (&cont[0] + size())); + } + template constexpr Span(const otb::Span& s) noexcept + : Span(s.data(), s.size()) + {} + constexpr Span(const Span& other) noexcept = default; + //@} + + /// shallow assignment + Span& operator=(Span const&) noexcept = default; + + /// No-op destructor + ~Span() = default; + + /**\name Iterators */ + //@{ + constexpr iterator begin () noexcept { return data(); } + constexpr iterator end () noexcept { return data()+size(); } + constexpr const_iterator begin () const noexcept { return data(); } + constexpr const_iterator end () const noexcept { return data()+size(); } + constexpr const_iterator cbegin() const noexcept { return data(); } + constexpr const_iterator cend () const noexcept { return data()+size(); } + + constexpr reverse_iterator rbegin () noexcept { return reverse_iterator(end()); } + constexpr reverse_iterator rend () noexcept { return reverse_iterator(begin()); } + constexpr const_reverse_iterator crbegin() const noexcept { return reverse_const_iterator(cend()); } + constexpr const_reverse_iterator crend () const noexcept { return reverse_const_iterator(cbegin()); } + //@} + + /**\name Element access */ + //@{ + constexpr pointer data () noexcept { return m_buffer; } + constexpr const_pointer data () const noexcept { return m_buffer; } + constexpr reference front() noexcept { assert(!empty()); return *data(); } + constexpr const_reference front() const noexcept { assert(!empty()); return *data(); } + constexpr reference back () noexcept { assert(!empty()); return *data()+size()-1; } + constexpr const_reference back () const noexcept { assert(!empty()); return *data()+size()-1; } + + constexpr reference operator[](index_type p) noexcept + { + assert(p < size()); + return data()[p]; + } + constexpr const_reference operator[](index_type p) const noexcept + { + assert(p < size()); + return data()[p]; + } + //@} + + /**\name Observers */ + //@{ + constexpr index_type size () const noexcept { return m_size; } + constexpr bool empty() const noexcept { return size() == 0; } + //@} + + /**\name Subviews */ + //@{ + constexpr Span first(index_type n) const noexcept + { assert(n < size()); return Span(data(), n);} + constexpr Span last(index_type n) const noexcept + { assert(n < size()); return Span(data()-n, n);} + //@} + +private: + pointer m_buffer = nullptr; + index_type m_size = 0; +}; + +/** + * Helper function to make a span from a range defined with pointers. + * Compensate the fact we are not have access to C++17 `span{ptr1, ptr2}`. + * \tparam T Auto deduced type of the elements + * \param[in] first start of the memory zone + * \param[in] last end of the memory zone + * \return a span over `[first, last)` + * \throw None + * \pre `NOT first != nullptr XOR last != nullptr` + * \pre `first < last` + * \pre `[first, last)` can be iterated + * \see `otb::Span<>` + * \author Luc Hermitte (CS Group) + * \copyright CNES + * \ingroup OTBCommon + */ +template +inline +auto make_span(T* first, T* last) noexcept +{ + return Span(first, last); +} + +/** + * Helper function to make a span from a range defined with a pointer plus a + * size. + * Compensate the fact we are not have access to C++17 `span{ptr, count}`. + * \tparam T Auto deduced type of the elements + * \param[in] first start of the memory zone + * \param[in] count number of elements in the span. + * \return a span over `[first, first+count)` + * \throw None + * \pre `NOT first != nullptr XOR count != 0` + * \see `otb::Span<>` + * \author Luc Hermitte (CS Group) + * \copyright CNES + * \ingroup OTBCommon + */ +template +inline +auto make_span(T* first, std::size_t count) noexcept +{ + return Span(first, count); +} + +/** + * Helper function to make a span from a static array. + * Compensate the fact we are not have access to C++17 `span{array}`. + * \tparam T Auto deduced type of the elements + * \tparam N Auto deduced number of elements in the array + * \param[in] array static array + * \return a span over `[&array[0], &array[N])` + * \throw None + * \see `otb::Span<>` + * \author Luc Hermitte (CS Group) + * \copyright CNES + * \ingroup OTBCommon + */ +template +inline +auto make_span(T (&arr)[N]) noexcept +{ + return Span(arr); +} + +/** + * Helper function to make a span from a contiguous container. + * Compensate the fact we are not have access to C++17 `span{container}`. + * \tparam ContiguousContainer Auto deduced type of the container + * \param[in] cont container of contiguous elements + * \return a span over `[c.data(), c.size())` + * \throw None + * \see `otb::Span<>` + * \author Luc Hermitte (CS Group) + * \copyright CNES + * \ingroup OTBCommon + */ +template +inline +auto make_span(ContiguousContainer & c) noexcept +{ + return Span(c); +} + +} +// otb namespace + + +#endif // Span_h diff --git a/Modules/Core/Common/include/otbZipIterator.h b/Modules/Core/Common/include/otbZipIterator.h new file mode 100644 index 0000000000..f95635a16a --- /dev/null +++ b/Modules/Core/Common/include/otbZipIterator.h @@ -0,0 +1,419 @@ +/* + * Copyright(C) 2005-2020 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. + */ + + +#ifndef otbZipIterator_h +#define otbZipIterator_h + +#include "otbSpan.h" +#include "itkMacro.h" +#include +#include +#include + +namespace otb +{ +namespace internals +{ + +struct ConstTag {}; +struct MutableTag {}; + +/** + * Wrapper to present list of iterators as a single iterator. + * + * \invariant This class shall not be inherited. + * \invariant All sub iterators are always synchronised (same region, size...) + * \invariant `!m_iterators.empty()` + * \author Luc Hermitte (CS Group) + * \copyright CNES + * \ingroup OTBCommon + */ +template +class ZipIterator +{ +public: + /**\name ITK Constants and Typedefs */ + //@{ + /** Iterator type for zipped iterators. */ + using ImageIteratorType = TImageIterator; + + /** Image type alias support */ + using ImageType = typename TImageIterator::ImageType; + + /** Dimension of the image the iterator walks. This constant is needed so + * functions that are templated over image iterator type (as opposed to + * being templated over pixel type and dimension) can have compile time + * access to the dimension of the image that the iterator walks. */ + static constexpr unsigned int ImageIteratorDimension = ImageIteratorType::ImageIteratorDimension; + + using Self = ZipIterator; + + /** Run-time type information (and related methods). */ + itkTypeMacroNoParent(ZipIterator); + + /** Index type alias support */ + using IndexType = typename ImageIteratorType::IndexType; + + /** Size type alias support */ + using SizeType = typename ImageIteratorType::SizeType; + + /** Offset type alias support */ + using OffsetType = typename ImageIteratorType::OffsetType; + + /** Region type alias support */ + using RegionType = typename ImageIteratorType::RegionType; + + /** PixelContainer type alias support. Used to refer to the container for + * the pixel data. While this was already typdef'ed in the superclass + * it needs to be redone here for this subclass to compile properly with gcc. */ + using PixelContainer = typename ImageIteratorType::PixelContainer; + using PixelContainerPointer = typename PixelContainer::Pointer; + + /** Internal Pixel Type */ + using InternalPixelType = typename ImageIteratorType::InternalPixelType; + + /** External Pixel Type */ + using PixelType = typename ImageIteratorType::PixelType; + + /** Accessor type that convert data between internal and external + * representations. */ + using AccessorType = typename ImageIteratorType::AccessorType; + using AccessorFunctorType = typename ImageIteratorType::AccessorFunctorType; + //@} + + /**\name Constructions & Destruction + * + * This class follows the rule of 0/5 + */ + //@{ + ZipIterator () = default; + ~ZipIterator () = default; + ZipIterator (ZipIterator const&) = default; + ZipIterator (ZipIterator &&) = default; + ZipIterator& operator=(ZipIterator const&) = default; + ZipIterator& operator=(ZipIterator &&) = default; + + /** Convertion constructor. + * Converts from mutable to const iterator + * \see https://quuxplusone.github.io/blog/2018/12/01/const-iterator-antipatterns/ + */ + template ::value, class = std::enable_if> + ZipIterator(ZipIterator const& rhs) + : m_iterators(rhs.m_iterators()) + {} + + /** Convertion move constructor. + * Move converts from mutable to const iterator + * \see https://quuxplusone.github.io/blog/2018/12/01/const-iterator-antipatterns/ + */ + template ::value, class = std::enable_if> + ZipIterator(ZipIterator && rhs) + : m_iterators(move(rhs.m_iterators())) + {} + + /** + * Init Constructor. + * Constructs a `ZipIterator` from a list of Images and a Region. + * \param[in,out] images List of images + * \param[in] region Region to iterate over + * \pre There should be at least one image + */ + ZipIterator(Span images, RegionType const& region) + { + assert(! images.empty()); + m_iterators.reserve(images.size()); + + for (auto & im: images) + m_iterators.emplace_back(im, region); + } + + // static_assert(std::is_copy_constructible::value, "Requires copy construction"); + // static_assert(std::is_trivially_copy_constructible::value, "Requires trivial copy construction"); + //@} + + /**\name Comparison */ + //@{ + friend bool operator==(ZipIterator const& lhs, ZipIterator const& rhs) + { + assert(!lhs.m_iterators.empty()); + assert(lhs.m_iterators.size() == rhs.m_iterators.size()); + + return lhs.m_iterators.front() == rhs.m_iterators.front(); + } + friend bool operator!=(ZipIterator const& lhs, ZipIterator const& rhs) + { return ! (lhs == rhs); } + + friend bool operator<=(ZipIterator const& lhs, ZipIterator const& rhs) + { + assert(!lhs.m_iterators.empty()); + assert(lhs.m_iterators.size() == rhs.m_iterators.size()); + + return lhs.m_iterators.front() <= rhs.m_iterators.front(); + } + friend bool operator<(ZipIterator const& lhs, ZipIterator const& rhs) + { + assert(!lhs.m_iterators.empty()); + assert(lhs.m_iterators.size() == rhs.m_iterators.size()); + + return lhs.m_iterators.front() < rhs.m_iterators.front(); + } + friend bool operator>=(ZipIterator const& lhs, ZipIterator const& rhs) + { return ! (lhs < rhs); } + friend bool operator>(ZipIterator const& lhs, ZipIterator const& rhs) + { return ! (lhs <= rhs); } + //@} + + /**\name ITK iterator interface */ + //@{ + // What about GetIndex() and SetIndex ? + /** Fetch the region iterated by the iterator. */ + auto const& GetRegion() const + { + assert(!m_iterators.empty()); + return m_iterators.front().GetRegion(); + } + + /** Set the region iterated by the iterator. */ + void SetRegion(RegionType const& region) + { + for (auto & it : m_iterators) + it.SetRegion(region); + } + + /** Moves the iterator to the begin of the region iterated. */ + Self& GoToBegin() { + for (auto & it : m_iterators) + it.GoToBegin(); + return *this; + } + /** Moves the iterator to the end of the region iterated. */ + Self& GoToEnd() { + for (auto & it : m_iterators) + it.GoToEnd(); + return *this; + } + + /** Tells whether the iterator is at the begin of the region iterated. */ + bool IsAtBegin() const { + assert(!m_iterators.empty()); + return m_iterators.front().IsAtBegin(); + } + + /** Tells the iterator is at the end of the region iterated. */ + bool IsAtEnd() const { + assert(!m_iterators.empty()); + return m_iterators.front().IsAtEnd(); + } + + /** Pre-increment the iterator. + * As post-increment is less efficient, it hasn't been provided. + */ + Self& operator++() { + assert(!IsAtEnd()); + for (auto & it : m_iterators) + ++it; + return *this; + } + /** Removed post-increment operator. + * Please use the preincrement operator! + */ + Self operator++(int) = delete; + + /** Internal typedef to the type holding the list of ITK iterators. */ + using ImageIteratorList_t = std::vector; + /** Internal Pixel Proxy Type returned by `ZipIterator`. + * \author Luc Hermitte (CS Group) + * \copyright CNES + * \ingroup OTBCommon + */ + struct PixelListProxy + { + /** Init constructor. + * @param[in] iterators List of ITK iterators + */ + explicit PixelListProxy(ImageIteratorList_t const& iterators) noexcept + : m_iterators(iterators) + {} + bool empty() const noexcept {return m_iterators.empty();} + auto size() const noexcept {return m_iterators.size();} + + /** Internal C++ iterator over the components of the Pixel Proxy. + * \author Luc Hermitte (CS Group) + * \copyright CNES + * \ingroup OTBCommon + */ + struct iterator__ + { + using difference_type = typename ImageIteratorList_t::difference_type; + using value_type = decltype(typename ImageIteratorList_t::const_iterator{}->Get()); + using pointer = value_type*; + using reference = value_type&; + using iterator_category = std::forward_iterator_tag; + + explicit iterator__(typename ImageIteratorList_t::const_iterator ref) + : reference_to_value(ref){} + friend bool operator==(iterator__ const& lhs, iterator__ const& rhs) noexcept + { return lhs.reference_to_value == rhs.reference_to_value;} + friend bool operator!=(iterator__ const& lhs, iterator__ const& rhs) noexcept + { return ! (lhs == rhs);} + iterator__ & operator++() noexcept { + ++reference_to_value; + return *this; + } + iterator__ & operator--() noexcept { + --reference_to_value; + return *this; + } + iterator__ operator+(std::ptrdiff_t offset) const noexcept{ + return iterator__{reference_to_value + offset}; + } + iterator__ operator-(std::ptrdiff_t offset) const noexcept{ + return iterator__{reference_to_value - offset}; + } + decltype(auto) operator*() const { + return reference_to_value->Get(); + } + + private: + typename ImageIteratorList_t::const_iterator reference_to_value; + }; + + auto begin() noexcept { return iterator__(m_iterators.begin()); } + auto end() noexcept { return iterator__{m_iterators.end()}; } + auto begin() const noexcept { return iterator__{m_iterators.begin()}; } + auto end() const noexcept { return iterator__{m_iterators.end()}; } + auto cbegin() const noexcept { return iterator__{m_iterators.cbegin()}; } + auto cend() const noexcept { return iterator__{m_iterators.cend()}; } + + decltype(auto) operator[](std::size_t idx) const { + assert(idx < size()); + return m_iterators[idx].Get(); + } + decltype(auto) operator[](std::size_t idx) { + assert(idx < size()); + return m_iterators[idx].Get(); + } + + decltype(auto) front() const { + assert(!empty()); + return m_iterators.front().Get(); + } + decltype(auto) front() { + assert(!empty()); + return m_iterators.front().Get(); + } + decltype(auto) back() const { + assert(!empty()); + return m_iterators.back().Get(); + } + decltype(auto) back() { + assert(!empty()); + return m_iterators.back().Get(); + } + private: + ImageIteratorList_t const& m_iterators; + }; + + /** Fetches the value of the current pixel. + * \return an iterable proxy over the pixel made of all images. + */ + PixelListProxy Get() const { + return PixelListProxy{m_iterators}; + } + + //@} + + /**\name Mutable Iterator Interface */ + //@{ + template + void Set(MultiCompPixelType const& p) + { + assert(p.size() == m_iterators.size()); + for (std::size_t i = 0; i!=m_iterators.size(); ++i) + { + m_iterators[i].Set(p[i]); + } + } + // PixelType & Value(); -- cannot be defined and still preserve direct access + // to memory => we don't provide it. + + // ImageType * GetImages(); + //@} + + /**\name ScanLine Iterator Interface */ + //@{ + /** Moves iterator to next line. */ + Self& NextLine() { + for (auto & it : m_iterators) + it.NextLine(); + return *this; + } + /** Moves iterator to the beginning of the current line. */ + Self& GoToBeginOfLine() { + for (auto & it : m_iterators) + it.GoToBeginOfLine(); + return *this; + } + /** Moves iterator to the end of the current line. */ + Self& GoToEndOfLine() { + for (auto & it : m_iterators) + it.GoToEndOfLine(); + return *this; + } + /** Tells whether the iterator is a the end of a line. + * \pre `!m_iterators.empty()` + */ + bool IsAtEndOfLine() const { + assert(!m_iterators.empty()); + // Const qualifier has been added to ScanLineIterator::IsAtEndOfLine in ITK + // 5.1 => Use const_cast in the mean time... + return const_cast(m_iterators.front()).IsAtEndOfLine(); + } + //@} + +private: + ImageIteratorList_t m_iterators; +}; + +} // otb::internal namespace + +/** Typedef for a ZipIterator. + * ZipIterator presents a single iterator over a list of image iterators. + * \author Luc Hermitte (CS Group) + * \copyright CNES + * \ingroup OTBCommon + * \see `otb::internals::ZipIterator<>` + */ +template +using ZipIterator = internals::ZipIterator; +/** Typedef for a ZipConstIterator. + * ZipConstIterator presents a single iterator over a list of const image iterators. + * \author Luc Hermitte (CS Group) + * \copyright CNES + * \ingroup OTBCommon + * \see `otb::internals::ZipIterator<>` + */ +template +using ZipConstIterator = internals::ZipIterator; + +} // otb namespace + +#endif // otbZipIterator_h diff --git a/Modules/Core/Functor/include/otbSynthetizeFilter.h b/Modules/Core/Functor/include/otbSynthetizeFilter.h new file mode 100644 index 0000000000..e86b3780a1 --- /dev/null +++ b/Modules/Core/Functor/include/otbSynthetizeFilter.h @@ -0,0 +1,239 @@ +/* + * Copyright(C) 2005-2020 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. + */ + + +#ifndef otbSynthetizeFilter_h +#define otbSynthetizeFilter_h + +#include "otbZipIterator.h" +#include "itkImageToImageFilter.h" +#include "itkImageScanlineConstIterator.h" +#include "itkImageScanlineIterator.h" +#include "itkProgressReporter.h" + +namespace otb +{ +/** + * Filter that reduces/synthetize multiple input into a single output. + * + * This filter makes sure to avoid VectorImages. Instead it works on a + * collection of scalar images. + * \tparam TInputImage Type of the input images + * \tparam TOutputImage Type of the output image + * \tparam TFunctor Type of the functor, meant to be auto-deduced by + * `MakeSynthetizeFilter()` + * + * \author Luc Hermitte (CS Group) + * \copyright CNES + * \see for instance `otb::Wrapper::Synthetize` + */ +template +class SynthetizeFilter : public itk::ImageToImageFilter +{ +public: + + /**\name Convenient typedefs for simplifying declarations */ + //@{ + using InputImageType = TInputImage; + using OutputImageType = TOutputImage; + using FunctorType = TFunctor; + //@} + + /**\name Extract dimension from input and output images */ + //@{ + itkStaticConstMacro(InputImageDimension, unsigned int, InputImageType::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, OutputImageType::ImageDimension); + //@} + /**\name Standard class typedefs */ + //@{ + using Self = SynthetizeFilter; + using Superclass = itk::ImageToImageFilter; + using Pointer = itk::SmartPointer; + using ConstPointer = itk::SmartPointer; + //@} + + /** Method for creation through the object factory. */ + static Pointer New(FunctorType functor) + { + Pointer smartPtr = new Self(std::move(functor)); + smartPtr->UnRegister(); + return smartPtr; + } + + /** Run-time type information (and related methods). */ + itkTypeMacro(SynthetizeFilter, ImageToImageFilter); + + /**\name Image typedef support */ + //@{ + using InputPixelType = typename InputImageType::PixelType; + using OutputPixelType = typename OutputImageType::PixelType; + using InputRealType = typename itk::NumericTraits::RealType; + using InputImageRegionType = typename InputImageType::RegionType; + using OutputImageRegionType = typename OutputImageType::RegionType; + using InputSizeType = typename InputImageType::SizeType; + using OutputIndexType = typename OutputImageType::IndexType; + using OutputSizeType = typename OutputImageType::SizeType; + + static_assert(InputImageDimension == OutputImageDimension, "Images have the same number of components"); + + using DataObjectPointerArraySizeType = itk::ProcessObject::DataObjectPointerArraySizeType; + //@} + + /**\name Access to N-th Input + * + * Set/Get the nth filter input with or without a specified associated + * variable name. + */ + //@{ + using Superclass::SetNthInput; + using Superclass::GetInput; + + /** Return a pointer on the nth filter input */ + InputImageType* GetNthInput(DataObjectPointerArraySizeType idx) + { + return const_cast(this->GetInput(idx)); + } + + /** Returns a vector of input images. */ + std::vector GetInputs() const + { + std::vector res; + auto const nbInputImages = this->GetNumberOfInputs(); + res.reserve(nbInputImages); + for (std::size_t i = 0 ; i != nbInputImages ; ++i) + res.push_back(this->GetInput(i)); + return res; + } + //@} + +protected: + /** Init constructor. */ + explicit SynthetizeFilter(FunctorType functor) + : m_functor(functor){} + ~SynthetizeFilter() = default; + + /** Overrides `GenerateOutputInformation` to check images consistency. */ + void GenerateOutputInformation() override + { + Superclass::GenerateOutputInformation(); + CheckInputImageDimensions(); + } + + // void GenerateInputRequestedRegion() override; + // +-> TODO: detect neighborhood to apply pad radius + + /** + * Main computation function called by each thread. + * \param[in] outputRegionForThread Specified output region to compute + * \param[in] threadId Id of the computing threads + */ + void ThreadedGenerateData( + OutputImageRegionType const& outputRegionForThread, + itk::ThreadIdType threadId) override + { + using ImageScanlineConstIteratorType = itk::ImageScanlineConstIterator; + using OutImageScanlineConstIteratorType = itk::ImageScanlineIterator; + using OutputIterator = itk::ImageScanlineIterator; + using InputIterator = ZipConstIterator; + + auto const regSizeY = outputRegionForThread.GetSize()[1]; + itk::ProgressReporter progress( this, threadId, outputRegionForThread.GetNumberOfPixels() / regSizeY ); + + InputIterator inputIterator(this->GetInputs(), outputRegionForThread); + OutputIterator outputIterator(this->GetOutput(), outputRegionForThread); + + inputIterator.GoToBegin(); + outputIterator.GoToBegin(); + for ( + ; !inputIterator.IsAtEnd() + ; inputIterator.NextLine(), outputIterator.NextLine()) + { + assert(! outputIterator.IsAtEnd()); + // inputIterator.GoToBeginOfLine(); + // outputIterator.GoToBeginOfLine(); + for ( + ; !inputIterator.IsAtEndOfLine() + ; ++inputIterator, ++outputIterator) + { + assert(!outputIterator.IsAtEndOfLine()); + + outputIterator.Set(m_functor(inputIterator.Get())); + } + progress.CompletedPixel(); // Completed...Line() + } + } + +private: + + void CheckInputImageDimensions() + { + // Check if input image dimensions match + auto const nbInputImages = this->GetNumberOfInputs(); + auto const& inputSize = this->GetInput(0)->GetLargestPossibleRegion().GetSize(); + + for (auto p = 1U; p < nbInputImages; ++p) + { + auto const& regionSize = this->GetInput(p)->GetLargestPossibleRegion().GetSize(); + if (inputSize != regionSize) + { + itkExceptionMacro(<< "Input images must have the same dimensions.\n" + << "band #1 is [" << inputSize[0] << ";" << inputSize[1] << "]\n" + << "band #" << p + 1 << " is [" << this->GetInput(p)->GetLargestPossibleRegion().GetSize(0) << ";" + << regionSize << "]"); + } + } + } + + /** Internal functor. + * Can only be set at filter creation through call to `New`. + */ + FunctorType m_functor; + +}; + +/** + * Factory function for `SynthetizeFilter`. + * `SynthetizeFilter` objects are best made thanks to this factory function + * that'll automatically deduce the type of the functor parameter. + * + * Actually, there is no other to create a `SynthetizeFilter<>` that'll call a + * lambda on each pixel. + * \tparam TInputImage Type of the input images + * \tparam TOutputImage Type of the output image + * \tparam TFunctor Type of the functor + * \param[in] functor The functor + * + * \return a new `SynthetizeFilter` object. + * \sa `SynthetizeFilter` + */ +template +auto MakeSynthetizeFilter(TFunctor functor) +{ + auto filter = SynthetizeFilter::New(std::move(functor)); + return filter; +} + +} // otb namespace + +#ifndef OTB_MANUAL_INSTANTIATION +// #include "otbSynthetizeFilter.hxx" +#endif + +#endif // otbSynthetizeFilter_h diff --git a/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.h b/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.h new file mode 100644 index 0000000000..e62e795a2d --- /dev/null +++ b/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.h @@ -0,0 +1,154 @@ +/* + * Copyright(C) 2005-2020 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. + */ + + +#ifndef otbClampROIFilter_h +#define otbClampROIFilter_h + +#include "itkImageToImageFilter.h" + +namespace otb +{ +/** + * Region clamping filter. + * This filter is a kind of ROI pass filter. Data within the ROI is kept with + * its original value. Data outside ROI is forced to 0. + * + * Also, this filter propagate the exact ROI upstream in the pipeline. This + * way, if it's piped after another filter, the upstream filter isn't executed + * on the data outside the ROI. + * + * \tparam TImage Image type. + * \sa `otb::ExtractROI<>` + * \author Luc Hermitte (CS Group) + * \copyright CNES + */ +template +class ClampROIFilter : public itk::ImageToImageFilter +{ +public: + + /**\name Convenient typedefs for simplifying declarations */ + //@{ + using InputImageType = TImage; + using OutputImageType = TImage; + //@} + + /**\name Extract dimension from input and output images */ + //@{ + itkStaticConstMacro(InputImageDimension, unsigned int, InputImageType::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, OutputImageType::ImageDimension); + //@} + /**\name Standard class typedefs */ + //@{ + using Self = ClampROIFilter; + using Superclass = itk::ImageToImageFilter; + using Pointer = itk::SmartPointer; + using ConstPointer = itk::SmartPointer; + //@} + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(ClampROIFilter, unused); + + /**\name Image typedef support */ + //@{ + using InputPixelType = typename InputImageType::PixelType; + using OutputPixelType = typename OutputImageType::PixelType; + using InputRealType = typename itk::NumericTraits::RealType; + using InputImageRegionType = typename InputImageType::RegionType; + using OutputImageRegionType = typename OutputImageType::RegionType; + using InputIndexType = typename InputImageType::IndexType; + using InputSizeType = typename InputImageType::SizeType; + using OutputIndexType = typename OutputImageType::IndexType; + using OutputSizeType = typename OutputImageType::SizeType; + + static_assert(InputImageDimension == OutputImageDimension, "Images have the same number of components"); + //@} + + /** Column threshold setter. */ + void SetThresholdX(long threshold) noexcept + { m_thresholdX = threshold; } + /** Column threshold getter. */ + long GetThresholdX() const noexcept + { return m_thresholdX;} + + /** Top line threshold setter. */ + void SetThresholdYtop(long threshold) noexcept + { m_thresholdYtop = threshold; } + /** Top line threshold getter. */ + long GetThresholdYtop() const noexcept + { return m_thresholdYtop;} + + /** Bottom line threshold setter. */ + void SetThresholdYbot(long threshold) noexcept + { m_thresholdYbot = threshold; } + /** Bottom line threshold getter. */ + long GetThresholdYbot() const noexcept + { return m_thresholdYbot;} + +protected: + /// Hidden constructor + ClampROIFilter() = default; + + InputImageType * GetInputImage() { return const_cast(this->GetInput()); } + InputImageType const* GetInputImage() const { return this->GetInput(); } + + /** otbClampROIFilter doesn't need an input requested region as large as the + * output requested region. + * \sa ImageToImageFilter::GenerateInputRequestedRegion() + */ + void CallCopyOutputRegionToInputRegion( + InputImageRegionType & destRegion, + OutputImageRegionType const& srcRegion) override + { + destRegion = OutputRegionToInputRegion(srcRegion); + } + + /** + * Functional implementation of `CallCopyOutputRegionToInputRegion()`. + */ + InputImageRegionType OutputRegionToInputRegion( + OutputImageRegionType const& srcRegion); + + /** + * Main computation function called by each thread. + * \param[in] outputRegionForThread Specified output region to compute + * \param[in] threadId Id of the computing threads + */ + void ThreadedGenerateData( + OutputImageRegionType const& outputRegionForThread, + itk::ThreadIdType threadId) override; + +private: + long m_thresholdX = 0; + long m_thresholdYtop = 0; + long m_thresholdYbot = 0; +}; + +} // otb namespace + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbClampROIFilter.hxx" +#endif + +#endif // otbClampROIFilter_h diff --git a/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx b/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx new file mode 100644 index 0000000000..fa40583c8c --- /dev/null +++ b/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx @@ -0,0 +1,216 @@ +/* + * Copyright(C) 2005-2020 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. + */ + + +#ifndef otbClampROIFilter_hxx +#define otbClampROIFilter_hxx + +#include "otbClampROIFilter.h" +#include "otbInterval.h" +#include "otbMacro.h" +#include "otbLogHelpers.h" +#include "itkImageScanlineConstIterator.h" +#include "itkImageScanlineIterator.h" +#include "itkProgressReporter.h" +#include +#include +#include +#include + +template +inline +std::ostream & operator<<(std::ostream & os, boost::numeric::interval const& v) +{ + return os << '[' << v.lower() << ".." << v.upper() << '['; +} + +namespace otb +{ + +template +void +ClampROIFilter +::ThreadedGenerateData( + OutputImageRegionType const& outputRegionForThread, + itk::ThreadIdType threadId) +{ + // otbMsgDevMacro("ThreadedGenerateData begin("<; + using OutputIterator = itk::ImageScanlineIterator; + + auto const* input = this->GetInput(); + auto * output = this->GetOutput(); + assert(input); + assert(output); + InputIterator inputIterator (input, OutputRegionToInputRegion(outputRegionForThread)); + OutputIterator outputIterator(output, outputRegionForThread); + + auto const& imgRegion = output->GetLargestPossibleRegion(); + auto const imgSizeX = imgRegion.GetSize()[0]; + auto const imgSizeY = imgRegion.GetSize()[1]; + itk::IndexValueType const imgEndX = imgRegion.GetIndex()[0] + imgSizeX; + itk::IndexValueType const imgEndY = imgRegion.GetIndex()[1] + imgSizeY; + + auto const& size = outputRegionForThread.GetSize(); + auto const& index = outputRegionForThread.GetIndex(); + auto const sizeX = size[0]; + auto const sizeY = size[1]; + auto const startX = index[0]; + auto const startY = index[1]; + itk::IndexValueType const endX = startX + sizeX; + itk::IndexValueType const endY = startY + sizeY; + auto const thrX1 = std::min(endX, m_thresholdX); + auto const thrX2 = std::min(endX, imgEndX - m_thresholdX); + auto const thrY1 = std::min(endY, m_thresholdYtop); + auto const thrY2 = std::min(endY, imgEndY - m_thresholdYbot); + + assert(thrX1 <= endX && "Iterations shall stay within requested region"); + assert(thrX2 <= endX && "Iterations shall stay within requested region"); + assert(thrY1 <= endY && "Iterations shall stay within requested region"); + assert(thrY2 <= endY && "Iterations shall stay within requested region"); + + // using interval_t = boost::numeric::interval; + using interval_t = Interval; + auto const region = interval_t{startX, endX}; + auto const zero_left = intersect(interval_t{startX, thrX1}, region); + auto const copy_middle = intersect(interval_t{thrX1, thrX2}, region); + auto const zero_right = intersect(interval_t{thrX2, endX}, region); + otbMsgDevMacro("X in " << zero_left << " <<-- 0"); + otbMsgDevMacro("X in " << copy_middle << " <<-- copy input"); + otbMsgDevMacro("X in " << zero_right << " <<-- 0"); + otbMsgDevMacro("Y in ["< +typename ClampROIFilter::InputImageRegionType +ClampROIFilter +::OutputRegionToInputRegion(OutputImageRegionType const& srcRegion) +{ + auto const* output = this->GetOutput(); + assert(output); + + auto const& maxRegion = output->GetLargestPossibleRegion(); + auto const& maxSize = maxRegion.GetSize(); + auto const& maxStart = maxRegion.GetIndex(); + + auto const& reqRegion = srcRegion; + auto const& reqSize = reqRegion.GetSize(); + auto const& reqStart = reqRegion.GetIndex(); + + // using interval_t = boost::numeric::interval; + using interval_t = Interval; + auto const maxRegionX = interval_t{ + maxStart[0]+m_thresholdX, + static_cast(maxStart[0]+maxSize[0]-m_thresholdX) + }; + auto const maxRegionY = interval_t{ + maxStart[1]+m_thresholdYtop, + static_cast(maxStart[1]+maxSize[1]-m_thresholdYbot) + }; + + auto const reqRegionX = interval_t::OfLength(reqStart[0], reqSize[0]); + auto const reqRegionY = interval_t::OfLength(reqStart[1], reqSize[1]); +#if 0 + otbMsgDevMacro("OutputRegionToInputRegion: " + << "out="<< NeatRegionLogger{reqRegion} + << "; max: x="< ∩X: " << inRegionX << " ∩Y: " << inRegionY); + + const InputIndexType inStart{inRegionX.lower(), inRegionY.lower()}; + assert(inRegionX.lower() <= inRegionX.upper()); + assert(inRegionY.lower() <= inRegionY.upper()); + const InputSizeType inSize{ + static_cast(inRegionX.upper()-inRegionX.lower()), + static_cast(inRegionY.upper()-inRegionY.lower()) + }; + auto const inRegion = InputImageRegionType{inStart, inSize}; + otbMsgDevMacro("OutputRegionToInputRegion: out="<< NeatRegionLogger{reqRegion}<<" --> in="< Date: Tue, 1 Sep 2020 17:50:46 +0200 Subject: [PATCH 06/16] DOC: Fix missing doc examples --- .../AppImageUtils/app/otbClampROI.cxx | 15 +++++++++++++-- .../AppImageUtils/app/otbSynthetize.cxx | 8 ++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Modules/Applications/AppImageUtils/app/otbClampROI.cxx b/Modules/Applications/AppImageUtils/app/otbClampROI.cxx index 0d49ca2433..2ff4cd2a15 100644 --- a/Modules/Applications/AppImageUtils/app/otbClampROI.cxx +++ b/Modules/Applications/AppImageUtils/app/otbClampROI.cxx @@ -53,7 +53,7 @@ private: { SetName("ClampROI"); - SetDescription("This is the ClampROI application, version X.X.X"); + SetDescription("This is the ClampROI application"); SetDocLongDescription( "This application is similar to ExtractROI in the sense it extracts a Region of Interrest.\n" "However, the region outside of the ROI isn't trimmed, but set to 0.\n" @@ -64,7 +64,7 @@ private: SetDocLimitations("This application only works on scalar (and complex) images."); SetDocAuthors("Luc Hermitte (CS Group)"); SetDocSeeAlso("ManageNoData, ExtractROI"); - AddDocTag("otb::Wrapper::Tags::Manip"); + AddDocTag(Tags::Manip); AddParameter(ParameterType_InputImage, "in", "Input image"); SetParameterDescription("in", "Scalar Input image"); @@ -88,7 +88,18 @@ private: SetParameterDescription("threshold.y.end", "Bottom line index threshold"); SetDefaultParameterInt("threshold.y.end", 0); + SetMinimumParameterIntValue("threshold.x", 0); + SetMinimumParameterIntValue("threshold.y.start", 0); + SetMinimumParameterIntValue("threshold.y.end", 0); + AddRAMParameter(); + + SetDocExampleParameterValue("in", "ClampROIInput100x100.tiff"); + SetDocExampleParameterValue("threshold.x", "10"); + SetDocExampleParameterValue("threshold.y.start", "12"); + SetDocExampleParameterValue("threshold.y.end", "25"); + SetDocExampleParameterValue("out", "ClampROI.tiff"); + SetOfficialDocLink(); } void DoUpdateParameters() override diff --git a/Modules/Applications/AppImageUtils/app/otbSynthetize.cxx b/Modules/Applications/AppImageUtils/app/otbSynthetize.cxx index fa77fdcba8..6862ed574b 100644 --- a/Modules/Applications/AppImageUtils/app/otbSynthetize.cxx +++ b/Modules/Applications/AppImageUtils/app/otbSynthetize.cxx @@ -60,14 +60,14 @@ private: { SetName("Synthetize"); - SetDescription("This is the Synthetize application, version X.X.X"); + SetDescription("This is the Synthetize application"); SetDocLongDescription("Concatenate a list of images of the same size into a single single-channel image.\n\ It keeps the first non-null pixel value found in the input list."); SetDocLimitations("This application will break incoming pipelines."); SetDocAuthors("Luc Hermitte (CS Group)"); SetDocSeeAlso(""); - AddDocTag("otb::Wrapper::Tags::Manip"); + AddDocTag(Tags::Manip); AddParameter(ParameterType_StringList, "il", "Input images list"); SetParameterDescription("il", "Input image list"); @@ -76,6 +76,10 @@ private: SetParameterDescription("out","Output image."); AddRAMParameter(); + + SetDocExampleParameterValue("il", "s1a_33NWB_vv_DES_007_20200108t044150.tif s1a_33NWB_vv_DES_007_20200108t044215.tif"); + SetDocExampleParameterValue("out", "s1a_33NWB_vv_DES_007_20200108txxxxxx.tif"); + SetOfficialDocLink(); } void DoUpdateParameters() override -- GitLab From b48514832c704ea98d99db6dbb57c2a9c7878f0e Mon Sep 17 00:00:00 2001 From: Luc Hermitte Date: Tue, 1 Sep 2020 17:51:34 +0200 Subject: [PATCH 07/16] WRN: Remove unused type warning --- Modules/Core/Functor/include/otbSynthetizeFilter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Core/Functor/include/otbSynthetizeFilter.h b/Modules/Core/Functor/include/otbSynthetizeFilter.h index e86b3780a1..574ac33e0f 100644 --- a/Modules/Core/Functor/include/otbSynthetizeFilter.h +++ b/Modules/Core/Functor/include/otbSynthetizeFilter.h @@ -149,7 +149,7 @@ protected: itk::ThreadIdType threadId) override { using ImageScanlineConstIteratorType = itk::ImageScanlineConstIterator; - using OutImageScanlineConstIteratorType = itk::ImageScanlineIterator; + // using OutImageScanlineConstIteratorType = itk::ImageScanlineIterator; using OutputIterator = itk::ImageScanlineIterator; using InputIterator = ZipConstIterator; -- GitLab From 6c6b133f408c05d89bd409a261e63708bcd22c2d Mon Sep 17 00:00:00 2001 From: Luc Hermitte Date: Tue, 1 Sep 2020 18:32:45 +0200 Subject: [PATCH 08/16] TST: Add tests for ClampROI & Synthetize --- .../Images/ClampROIBaseline100x100.tiff | 3 + ...NWB_vv_DES_007_20200108txxxxxx_100x100.tif | 3 + Data/Input/ClampROIInput100x100.tiff | 3 + ...NWB_vv_DES_007_20200108t044150_100x100.tif | 3 + ...NWB_vv_DES_007_20200108t044215_100x100.tif | 3 + .../AppImageUtils/test/CMakeLists.txt | 56 +++++++++++++------ 6 files changed, 54 insertions(+), 17 deletions(-) create mode 100644 Data/Baseline/OTB-Applications/Images/ClampROIBaseline100x100.tiff create mode 100644 Data/Baseline/OTB-Applications/Images/s1a_33NWB_vv_DES_007_20200108txxxxxx_100x100.tif create mode 100644 Data/Input/ClampROIInput100x100.tiff create mode 100644 Data/Input/s1a_33NWB_vv_DES_007_20200108t044150_100x100.tif create mode 100644 Data/Input/s1a_33NWB_vv_DES_007_20200108t044215_100x100.tif diff --git a/Data/Baseline/OTB-Applications/Images/ClampROIBaseline100x100.tiff b/Data/Baseline/OTB-Applications/Images/ClampROIBaseline100x100.tiff new file mode 100644 index 0000000000..d687d442d2 --- /dev/null +++ b/Data/Baseline/OTB-Applications/Images/ClampROIBaseline100x100.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c8358d04f4d40cdbf08c836bba4ff725c7f8d1d0daeef8c2d336090a240c928 +size 33041 diff --git a/Data/Baseline/OTB-Applications/Images/s1a_33NWB_vv_DES_007_20200108txxxxxx_100x100.tif b/Data/Baseline/OTB-Applications/Images/s1a_33NWB_vv_DES_007_20200108txxxxxx_100x100.tif new file mode 100644 index 0000000000..59d9650a2b --- /dev/null +++ b/Data/Baseline/OTB-Applications/Images/s1a_33NWB_vv_DES_007_20200108txxxxxx_100x100.tif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1b49117a90f751d70f80f1c79975a6a45fbd278d349e2e77844050f641774c5 +size 34870 diff --git a/Data/Input/ClampROIInput100x100.tiff b/Data/Input/ClampROIInput100x100.tiff new file mode 100644 index 0000000000..ee84e4b93e --- /dev/null +++ b/Data/Input/ClampROIInput100x100.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a1354f27b0141d6e7c58fcce825e4f988dc135aeed0a45a051aeb658c6bcf653 +size 50506 diff --git a/Data/Input/s1a_33NWB_vv_DES_007_20200108t044150_100x100.tif b/Data/Input/s1a_33NWB_vv_DES_007_20200108t044150_100x100.tif new file mode 100644 index 0000000000..4d4e02c34b --- /dev/null +++ b/Data/Input/s1a_33NWB_vv_DES_007_20200108t044150_100x100.tif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:99bde32908be865a70b59524ad0ca0e984490a1d46b4675d714e740209dba608 +size 19628 diff --git a/Data/Input/s1a_33NWB_vv_DES_007_20200108t044215_100x100.tif b/Data/Input/s1a_33NWB_vv_DES_007_20200108t044215_100x100.tif new file mode 100644 index 0000000000..23e2b6bd72 --- /dev/null +++ b/Data/Input/s1a_33NWB_vv_DES_007_20200108t044215_100x100.tif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53a6a9e06b772c692f581117289168b14f077fab863280202a1bc9a9160e6043 +size 16763 diff --git a/Modules/Applications/AppImageUtils/test/CMakeLists.txt b/Modules/Applications/AppImageUtils/test/CMakeLists.txt index 350b31b3df..674fdb043a 100644 --- a/Modules/Applications/AppImageUtils/test/CMakeLists.txt +++ b/Modules/Applications/AppImageUtils/test/CMakeLists.txt @@ -120,6 +120,18 @@ otb_test_application(NAME apTvUtExtractROIExtentFitVect ${OTBAPP_BASELINE}/apTvUtExtractROI.tif ${TEMP}/apTvUtExtractROIExtentFitVect.tif) +#----------- Clamp ROI tests ---------------- +otb_test_application(NAME apTvUtClampROI + APP ClampROI + OPTIONS -in ${INPUTDATA}/ClampROIInput100x100.tiff + -out ${TEMP}/apTvUtClampROI.tif + -threshold.x 10 + -threshold.y.start 12 + -threshold.y.end 25 + VALID --compare-image ${NOTOL} + ${OTBAPP_BASELINE}/ClampROIBaseline100x100.tiff + ${TEMP}/apTvUtClampROI.tif) + #----------- Rescale TESTS ---------------- otb_test_application(NAME apTvUtRescaleTest APP Rescale @@ -252,6 +264,16 @@ otb_test_application(NAME apTvUtConcatenateImages_1Image ${TEMP}/apTvUtConcatenateImages_1Image.tif) +#----------- Synthetize TESTS ---------------- +otb_test_application(NAME apTvUtSynthetize + APP Synthetize + OPTIONS -il ${INPUTDATA}/s1a_33NWB_vv_DES_007_20200108t044150_100x100.tif + ${INPUTDATA}/s1a_33NWB_vv_DES_007_20200108t044215_100x100.tif + -out ${TEMP}/apTvUtSynthetize.tif + VALID --compare-image ${NOTOL} + ${OTBAPP_BASELINE}/s1a_33NWB_vv_DES_007_20200108txxxxxx_100x100.tif + ${TEMP}/apTvUtSynthetize.tif) + #----------- MultiResolutionPyramid TESTS ---------------- #----------- PixelValue TESTS ---------------- @@ -443,8 +465,8 @@ otb_test_application(NAME apTvUtSplitImage #----------- Mosaic TESTS ---------------- otb_test_application(NAME MosaicTestLargeFeathering APP Mosaic - OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif - -out ${TEMP}/apTvMosaicTestLargeFeathering.tif uint8 + OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif + -out ${TEMP}/apTvMosaicTestLargeFeathering.tif uint8 -comp.feather large VALID --compare-image ${EPSILON_8} ${BASELINE}/apTvMosaicTestLargeFeathering.tif @@ -453,9 +475,9 @@ otb_test_application(NAME MosaicTestLargeFeathering otb_test_application(NAME MosaicTestSlimFeathering APP Mosaic - OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif - -out ${TEMP}/apTvMosaicTestSlimFeathering.tif uint8 - -comp.feather slim + OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif + -out ${TEMP}/apTvMosaicTestSlimFeathering.tif uint8 + -comp.feather slim -comp.feather.slim.length 100 VALID --compare-image ${EPSILON_8} ${BASELINE}/apTvMosaicTestSlimFeathering.tif @@ -464,9 +486,9 @@ otb_test_application(NAME MosaicTestSlimFeathering otb_test_application(NAME MosaicTestSimpleWithHarmoBandRmse APP Mosaic - OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif - -out ${TEMP}/apTvMosaicTestSimpleWithHarmoBandRmse.tif uint8 - -harmo.method band + OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif + -out ${TEMP}/apTvMosaicTestSimpleWithHarmoBandRmse.tif uint8 + -harmo.method band -harmo.cost rmse VALID --compare-image ${EPSILON_8} ${BASELINE}/apTvMosaicTestSimpleWithHarmoBandRmse.tif @@ -474,9 +496,9 @@ otb_test_application(NAME MosaicTestSimpleWithHarmoBandRmse otb_test_application(NAME MosaicTestSimpleWithHarmoRgbRmse APP Mosaic - OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif - -out ${TEMP}/apTvMosaicTestSimpleWithHarmoRgbRmse.tif uint8 - -harmo.method rgb + OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif + -out ${TEMP}/apTvMosaicTestSimpleWithHarmoRgbRmse.tif uint8 + -harmo.method rgb -harmo.cost rmse VALID --compare-image ${EPSILON_8} ${BASELINE}/apTvMosaicTestSimpleWithHarmoRgbRmse.tif @@ -484,18 +506,18 @@ otb_test_application(NAME MosaicTestSimpleWithHarmoRgbRmse otb_test_application(NAME MosaicTestSimpleWithCutline APP Mosaic - OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif - -out ${TEMP}/apTvMosaicTestSimpleWithCutline.tif uint8 - -vdcut ${INPUTDATA}/SP67_FR_subset_1_cutline.shp ${INPUTDATA}/SP67_FR_subset_2_cutline.shp + OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif + -out ${TEMP}/apTvMosaicTestSimpleWithCutline.tif uint8 + -vdcut ${INPUTDATA}/SP67_FR_subset_1_cutline.shp ${INPUTDATA}/SP67_FR_subset_2_cutline.shp VALID --compare-image ${EPSILON_8} ${BASELINE}/apTvMosaicTestSimpleWithCutline.tif ${TEMP}/apTvMosaicTestSimpleWithCutline.tif) otb_test_application(NAME MosaicTestSimpleWithVdstats APP Mosaic - OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif - -out ${TEMP}/apTvMosaicTestSimpleWithVdstats.tif uint8 - -vdstats ${INPUTDATA}/SP67_FR_subset_1_cutline.shp ${INPUTDATA}/SP67_FR_subset_2_cutline.shp + OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif + -out ${TEMP}/apTvMosaicTestSimpleWithVdstats.tif uint8 + -vdstats ${INPUTDATA}/SP67_FR_subset_1_cutline.shp ${INPUTDATA}/SP67_FR_subset_2_cutline.shp VALID --compare-image ${EPSILON_8} ${BASELINE}/apTvMosaicTestSimpleWithVdstats.tif ${TEMP}/apTvMosaicTestSimpleWithVdstats.tif) -- GitLab From 38185c42fd0ccdd98b47a3fdb9745af60788e47d Mon Sep 17 00:00:00 2001 From: Luc Hermitte Date: Wed, 2 Sep 2020 10:40:10 +0200 Subject: [PATCH 09/16] ENH: Improve `Span` documentation and add `subspan` --- Modules/Core/Common/include/otbSpan.h | 31 +++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/Modules/Core/Common/include/otbSpan.h b/Modules/Core/Common/include/otbSpan.h index 0b39f86736..a160b4ec09 100644 --- a/Modules/Core/Common/include/otbSpan.h +++ b/Modules/Core/Common/include/otbSpan.h @@ -24,12 +24,25 @@ #include #include +#include #include namespace otb { /** Span class inspired by C++20 standard. + * + * \invariant `size() == 0 or data() != nullptr` + * + * \note Unlike C++20 `std::span` this implementation doesn't follow Lakos + * Rule but instead non-throwing functions are `noexcept` as suggested in + * https://wg21.link/p1656. Beware to not expect `operator[]` to always be + * `noexcept` as it won't be anymore once this class is deprecated in favour + * of `std::span` in a few years. + * + * \note This implementation only support spans with dynamic extents. Static + * extents are not supported (yet?) + * * \todo fix RW / RO interface * \author Luc Hermitte (CS Group) * \copyright CNES @@ -75,7 +88,7 @@ template struct Span * \pre The Container shall be contiguous * \warning The lifetime of the span shall not exceed the one of the container. * Be sure to not store the span locally, and initialize it from a rvalue. - * The use case where a span is initialize from a rvalue shall be restricted + * The use case where a span is initialized from a rvalue shall be restricted * to function parameters. * \code * std::vector f(); @@ -88,10 +101,11 @@ template struct Span * \todo static_assert the container is contiguous */ template constexpr Span(Container&& cont) noexcept - : Span(&cont[0], cont.size()) + : Span(cont.data(), cont.size()) { // We cannot use op[] which has an assertion sometimes. // assert(&const[size()] == (&cont[0] + size())); + // Beside, it's not noexcept. } template constexpr Span(const otb::Span& s) noexcept : Span(s.data(), s.size()) @@ -153,6 +167,19 @@ template struct Span { assert(n < size()); return Span(data(), n);} constexpr Span last(index_type n) const noexcept { assert(n < size()); return Span(data()-n, n);} + + constexpr Span subspan(index_type offset, index_type count = std::numeric_limits::max()) noexcept + { + assert(offset <= size()); + if (count == std::numeric_limits::max()) + { + count = size() - offset; + } + + assert(count <= (size() - offset)); + return Span(data()+offset, count); + + } //@} private: -- GitLab From d6c664200103d389c20a30399ac77019bda6f4ca Mon Sep 17 00:00:00 2001 From: Luc Hermitte Date: Wed, 2 Sep 2020 11:24:44 +0200 Subject: [PATCH 10/16] TST: Register S1TilingSupportApplications tests --- CI/configure_options.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/configure_options.cmake b/CI/configure_options.cmake index 25a271891b..2f10ee0e99 100644 --- a/CI/configure_options.cmake +++ b/CI/configure_options.cmake @@ -70,7 +70,7 @@ if(XDK_PATH) set(cmake_configure_option "${cmake_configure_option} CMAKE_PREFIX_PATH=${XDK_PATH}") -foreach(remote_module OTBTemporalGapFilling SertitObject otbGRM DiapOTBModule) +foreach(remote_module OTBTemporalGapFilling SertitObject otbGRM DiapOTBModule S1TilingSupportApplications) set(cmake_configure_option "${cmake_configure_option} Module_${remote_module}:BOOL=ON") -- GitLab From e75c94c11ba8a3187baa8e186593f443b8a3abfd Mon Sep 17 00:00:00 2001 From: Luc Hermitte Date: Wed, 2 Sep 2020 17:31:44 +0200 Subject: [PATCH 11/16] COM: Fix (c) headers --- Modules/Applications/AppImageUtils/app/otbClampROI.cxx | 8 ++++---- Modules/Applications/AppImageUtils/app/otbSynthetize.cxx | 9 ++++----- Modules/Core/Common/include/otbInterval.h | 9 ++++----- Modules/Core/Common/include/otbLogHelpers.h | 9 ++++----- Modules/Core/Common/include/otbSpan.h | 9 ++++----- Modules/Core/Common/include/otbZipIterator.h | 9 ++++----- Modules/Core/Functor/include/otbSynthetizeFilter.h | 9 ++++----- .../ImageManipulation/include/otbClampROIFilter.h | 9 ++++----- .../ImageManipulation/include/otbClampROIFilter.hxx | 9 ++++----- 9 files changed, 36 insertions(+), 44 deletions(-) diff --git a/Modules/Applications/AppImageUtils/app/otbClampROI.cxx b/Modules/Applications/AppImageUtils/app/otbClampROI.cxx index 2ff4cd2a15..74bca802d1 100644 --- a/Modules/Applications/AppImageUtils/app/otbClampROI.cxx +++ b/Modules/Applications/AppImageUtils/app/otbClampROI.cxx @@ -1,15 +1,15 @@ /* - * Copyright(C) 2005-2020 Centre National d'Etudes Spatiales(CNES) + * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES) * * This file is part of Orfeo Toolbox * - * https: //www.orfeo-toolbox.org/ + * https://www.orfeo-toolbox.org/ * - * Licensed under the Apache License, Version 2.0(the "License"); + * 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 + * 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, diff --git a/Modules/Applications/AppImageUtils/app/otbSynthetize.cxx b/Modules/Applications/AppImageUtils/app/otbSynthetize.cxx index 6862ed574b..027a70908b 100644 --- a/Modules/Applications/AppImageUtils/app/otbSynthetize.cxx +++ b/Modules/Applications/AppImageUtils/app/otbSynthetize.cxx @@ -1,15 +1,15 @@ /* - * Copyright(C) 2005-2020 Centre National d'Etudes Spatiales(CNES) + * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES) * * This file is part of Orfeo Toolbox * - * https: //www.orfeo-toolbox.org/ + * https://www.orfeo-toolbox.org/ * - * Licensed under the Apache License, Version 2.0(the "License"); + * 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 + * 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, @@ -18,7 +18,6 @@ * limitations under the License. */ - #include "otbSynthetizeFilter.h" #include "otbWrapperApplication.h" #include "otbWrapperApplicationFactory.h" diff --git a/Modules/Core/Common/include/otbInterval.h b/Modules/Core/Common/include/otbInterval.h index 5e6ce66b9b..3aecaf0714 100644 --- a/Modules/Core/Common/include/otbInterval.h +++ b/Modules/Core/Common/include/otbInterval.h @@ -1,15 +1,15 @@ /* - * Copyright(C) 2005-2020 Centre National d'Etudes Spatiales(CNES) + * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES) * * This file is part of Orfeo Toolbox * - * https: //www.orfeo-toolbox.org/ + * https://www.orfeo-toolbox.org/ * - * Licensed under the Apache License, Version 2.0(the "License"); + * 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 + * 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, @@ -18,7 +18,6 @@ * limitations under the License. */ - #ifndef otbInterval_h #define otbInterval_h diff --git a/Modules/Core/Common/include/otbLogHelpers.h b/Modules/Core/Common/include/otbLogHelpers.h index 98239512b3..f205a69355 100644 --- a/Modules/Core/Common/include/otbLogHelpers.h +++ b/Modules/Core/Common/include/otbLogHelpers.h @@ -1,15 +1,15 @@ /* - * Copyright(C) 2005-2020 Centre National d'Etudes Spatiales(CNES) + * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES) * * This file is part of Orfeo Toolbox * - * https: //www.orfeo-toolbox.org/ + * https://www.orfeo-toolbox.org/ * - * Licensed under the Apache License, Version 2.0(the "License"); + * 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 + * 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, @@ -18,7 +18,6 @@ * limitations under the License. */ - #ifndef otbLogHelpers_h #define otbLogHelpers_h diff --git a/Modules/Core/Common/include/otbSpan.h b/Modules/Core/Common/include/otbSpan.h index a160b4ec09..74c1a4841d 100644 --- a/Modules/Core/Common/include/otbSpan.h +++ b/Modules/Core/Common/include/otbSpan.h @@ -1,15 +1,15 @@ /* - * Copyright(C) 2005-2020 Centre National d'Etudes Spatiales(CNES) + * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES) * * This file is part of Orfeo Toolbox * - * https: //www.orfeo-toolbox.org/ + * https://www.orfeo-toolbox.org/ * - * Licensed under the Apache License, Version 2.0(the "License"); + * 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 + * 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, @@ -18,7 +18,6 @@ * limitations under the License. */ - #ifndef Span_h #define Span_h diff --git a/Modules/Core/Common/include/otbZipIterator.h b/Modules/Core/Common/include/otbZipIterator.h index f95635a16a..6796d9697f 100644 --- a/Modules/Core/Common/include/otbZipIterator.h +++ b/Modules/Core/Common/include/otbZipIterator.h @@ -1,15 +1,15 @@ /* - * Copyright(C) 2005-2020 Centre National d'Etudes Spatiales(CNES) + * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES) * * This file is part of Orfeo Toolbox * - * https: //www.orfeo-toolbox.org/ + * https://www.orfeo-toolbox.org/ * - * Licensed under the Apache License, Version 2.0(the "License"); + * 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 + * 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, @@ -18,7 +18,6 @@ * limitations under the License. */ - #ifndef otbZipIterator_h #define otbZipIterator_h diff --git a/Modules/Core/Functor/include/otbSynthetizeFilter.h b/Modules/Core/Functor/include/otbSynthetizeFilter.h index 574ac33e0f..88393bcf1a 100644 --- a/Modules/Core/Functor/include/otbSynthetizeFilter.h +++ b/Modules/Core/Functor/include/otbSynthetizeFilter.h @@ -1,15 +1,15 @@ /* - * Copyright(C) 2005-2020 Centre National d'Etudes Spatiales(CNES) + * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES) * * This file is part of Orfeo Toolbox * - * https: //www.orfeo-toolbox.org/ + * https://www.orfeo-toolbox.org/ * - * Licensed under the Apache License, Version 2.0(the "License"); + * 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 + * 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, @@ -18,7 +18,6 @@ * limitations under the License. */ - #ifndef otbSynthetizeFilter_h #define otbSynthetizeFilter_h diff --git a/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.h b/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.h index e62e795a2d..807675349a 100644 --- a/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.h +++ b/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.h @@ -1,15 +1,15 @@ /* - * Copyright(C) 2005-2020 Centre National d'Etudes Spatiales(CNES) + * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES) * * This file is part of Orfeo Toolbox * - * https: //www.orfeo-toolbox.org/ + * https://www.orfeo-toolbox.org/ * - * Licensed under the Apache License, Version 2.0(the "License"); + * 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 + * 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, @@ -18,7 +18,6 @@ * limitations under the License. */ - #ifndef otbClampROIFilter_h #define otbClampROIFilter_h diff --git a/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx b/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx index fa40583c8c..a1029fef94 100644 --- a/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx +++ b/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx @@ -1,15 +1,15 @@ /* - * Copyright(C) 2005-2020 Centre National d'Etudes Spatiales(CNES) + * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES) * * This file is part of Orfeo Toolbox * - * https: //www.orfeo-toolbox.org/ + * https://www.orfeo-toolbox.org/ * - * Licensed under the Apache License, Version 2.0(the "License"); + * 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 + * 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, @@ -18,7 +18,6 @@ * limitations under the License. */ - #ifndef otbClampROIFilter_hxx #define otbClampROIFilter_hxx -- GitLab From 528ff2beb7dd725a748c4d3a7832dea064d52399 Mon Sep 17 00:00:00 2001 From: Luc Hermitte Date: Wed, 2 Sep 2020 19:20:56 +0200 Subject: [PATCH 12/16] COMP: Add missing header for `otbIterval.h` --- Modules/Core/Common/include/otbInterval.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/Core/Common/include/otbInterval.h b/Modules/Core/Common/include/otbInterval.h index 3aecaf0714..39ea6344c3 100644 --- a/Modules/Core/Common/include/otbInterval.h +++ b/Modules/Core/Common/include/otbInterval.h @@ -22,6 +22,7 @@ #define otbInterval_h #include "itkIntTypes.h" +#include #include #include -- GitLab From d11d66a2feca0209be75e24efb9e8ef101f4e05f Mon Sep 17 00:00:00 2001 From: Luc Hermitte Date: Wed, 2 Sep 2020 19:49:42 +0200 Subject: [PATCH 13/16] COMP: Work around MSVC not C++14 compliant --- Modules/Core/Common/include/otbInterval.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Modules/Core/Common/include/otbInterval.h b/Modules/Core/Common/include/otbInterval.h index 39ea6344c3..f37c2c0434 100644 --- a/Modules/Core/Common/include/otbInterval.h +++ b/Modules/Core/Common/include/otbInterval.h @@ -47,7 +47,9 @@ public: constexpr Interval(IndexType l, IndexType u) noexcept : m_lower(l), m_upper(u) { +#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304 assert(l <= u); +#endif } /** Alternate factory function from a position and a length. */ @@ -76,10 +78,17 @@ public: friend constexpr Interval intersect( Interval const& lhs, Interval const& rhs) noexcept { +#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304 auto const low = std::max(lhs.lower(), rhs.lower()); auto const upp = std::min(lhs.upper(), rhs.upper()); return low <= upp ? Interval{low, upp} : Interval{0,0}; +#else + // MSVC version supported is not C++14 compliant + return std::max(lhs.lower(), rhs.lower()) <= std::min(lhs.upper(), rhs.upper()) + ? Interval{std::max(lhs.lower(), rhs.lower()), std::min(lhs.upper(), rhs.upper())} + : Interval{0,0}; +#endif } /** Stream inserter for intervals. -- GitLab From 92f44062c986737840579ed2434e03e561c25ea4 Mon Sep 17 00:00:00 2001 From: Luc Hermitte Date: Thu, 3 Sep 2020 10:48:06 +0200 Subject: [PATCH 14/16] COMP: Workaround VC++14 non compliance to C++14 --- Modules/Core/Common/include/otbSpan.h | 28 ++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/Modules/Core/Common/include/otbSpan.h b/Modules/Core/Common/include/otbSpan.h index 74c1a4841d..93d27f4617 100644 --- a/Modules/Core/Common/include/otbSpan.h +++ b/Modules/Core/Common/include/otbSpan.h @@ -28,6 +28,16 @@ namespace otb { +#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304 + // In C++ (only; fixed in C++14), constexpr implies const on member + // functions, and OTB support VC++14 which is not C++14 compliant on this + // topic. + // Hence the workaround... + // TODO: get rid with this hack along VC++14 +# define OTB_MB_CSTXPR constexpr +#else +# define OTB_MB_CSTXPR +#endif /** Span class inspired by C++20 standard. * @@ -120,29 +130,29 @@ template struct Span /**\name Iterators */ //@{ - constexpr iterator begin () noexcept { return data(); } - constexpr iterator end () noexcept { return data()+size(); } + OTB_MB_CSTXPR iterator begin () noexcept { return data(); } + OTB_MB_CSTXPR iterator end () noexcept { return data()+size(); } constexpr const_iterator begin () const noexcept { return data(); } constexpr const_iterator end () const noexcept { return data()+size(); } constexpr const_iterator cbegin() const noexcept { return data(); } constexpr const_iterator cend () const noexcept { return data()+size(); } - constexpr reverse_iterator rbegin () noexcept { return reverse_iterator(end()); } - constexpr reverse_iterator rend () noexcept { return reverse_iterator(begin()); } + OTB_MB_CSTXPR reverse_iterator rbegin () noexcept { return reverse_iterator(end()); } + OTB_MB_CSTXPR reverse_iterator rend () noexcept { return reverse_iterator(begin()); } constexpr const_reverse_iterator crbegin() const noexcept { return reverse_const_iterator(cend()); } constexpr const_reverse_iterator crend () const noexcept { return reverse_const_iterator(cbegin()); } //@} /**\name Element access */ //@{ - constexpr pointer data () noexcept { return m_buffer; } + OTB_MB_CSTXPR pointer data () noexcept { return m_buffer; } constexpr const_pointer data () const noexcept { return m_buffer; } - constexpr reference front() noexcept { assert(!empty()); return *data(); } + OTB_MB_CSTXPR reference front() noexcept { assert(!empty()); return *data(); } constexpr const_reference front() const noexcept { assert(!empty()); return *data(); } - constexpr reference back () noexcept { assert(!empty()); return *data()+size()-1; } + OTB_MB_CSTXPR reference back () noexcept { assert(!empty()); return *data()+size()-1; } constexpr const_reference back () const noexcept { assert(!empty()); return *data()+size()-1; } - constexpr reference operator[](index_type p) noexcept + OTB_MB_CSTXPR reference operator[](index_type p) noexcept { assert(p < size()); return data()[p]; @@ -167,7 +177,7 @@ template struct Span constexpr Span last(index_type n) const noexcept { assert(n < size()); return Span(data()-n, n);} - constexpr Span subspan(index_type offset, index_type count = std::numeric_limits::max()) noexcept + constexpr Span subspan(index_type offset, index_type count = std::numeric_limits::max()) const noexcept { assert(offset <= size()); if (count == std::numeric_limits::max()) -- GitLab From ae7c29b0ee98d6c369e1aa56165e2b69710a9621 Mon Sep 17 00:00:00 2001 From: Luc Hermitte Date: Thu, 3 Sep 2020 10:54:45 +0200 Subject: [PATCH 15/16] COMP: workaround another VC++14 eccentricity --- .../ImageManipulation/include/otbClampROIFilter.hxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx b/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx index a1029fef94..7e893a37c7 100644 --- a/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx +++ b/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx @@ -75,10 +75,10 @@ ClampROIFilter auto const startY = index[1]; itk::IndexValueType const endX = startX + sizeX; itk::IndexValueType const endY = startY + sizeY; - auto const thrX1 = std::min(endX, m_thresholdX); - auto const thrX2 = std::min(endX, imgEndX - m_thresholdX); - auto const thrY1 = std::min(endY, m_thresholdYtop); - auto const thrY2 = std::min(endY, imgEndY - m_thresholdYbot); + auto const thrX1 = std::min(endX, m_thresholdX); + auto const thrX2 = std::min(endX, imgEndX - m_thresholdX); + auto const thrY1 = std::min(endY, m_thresholdYtop); + auto const thrY2 = std::min(endY, imgEndY - m_thresholdYbot); assert(thrX1 <= endX && "Iterations shall stay within requested region"); assert(thrX2 <= endX && "Iterations shall stay within requested region"); -- GitLab From de0bdbff5b2e652c049b78982a94dff63dc594ef Mon Sep 17 00:00:00 2001 From: Luc Hermitte Date: Thu, 10 Sep 2020 14:18:20 +0200 Subject: [PATCH 16/16] REFACT: Rename ClampROI into ResetMargin --- ...0.tiff => ResetMarginBaseline100x100.tiff} | 0 ...x100.tiff => ResetMarginInput100x100.tiff} | 0 .../AppImageUtils/app/CMakeLists.txt | 4 ++-- .../{otbClampROI.cxx => otbResetMargin.cxx} | 22 +++++++++---------- .../AppImageUtils/test/CMakeLists.txt | 12 +++++----- ...lampROIFilter.h => otbResetMarginFilter.h} | 18 +++++++-------- ...ROIFilter.hxx => otbResetMarginFilter.hxx} | 14 ++++++------ 7 files changed, 35 insertions(+), 35 deletions(-) rename Data/Baseline/OTB-Applications/Images/{ClampROIBaseline100x100.tiff => ResetMarginBaseline100x100.tiff} (100%) rename Data/Input/{ClampROIInput100x100.tiff => ResetMarginInput100x100.tiff} (100%) rename Modules/Applications/AppImageUtils/app/{otbClampROI.cxx => otbResetMargin.cxx} (88%) rename Modules/Filtering/ImageManipulation/include/{otbClampROIFilter.h => otbResetMarginFilter.h} (92%) rename Modules/Filtering/ImageManipulation/include/{otbClampROIFilter.hxx => otbResetMarginFilter.hxx} (97%) diff --git a/Data/Baseline/OTB-Applications/Images/ClampROIBaseline100x100.tiff b/Data/Baseline/OTB-Applications/Images/ResetMarginBaseline100x100.tiff similarity index 100% rename from Data/Baseline/OTB-Applications/Images/ClampROIBaseline100x100.tiff rename to Data/Baseline/OTB-Applications/Images/ResetMarginBaseline100x100.tiff diff --git a/Data/Input/ClampROIInput100x100.tiff b/Data/Input/ResetMarginInput100x100.tiff similarity index 100% rename from Data/Input/ClampROIInput100x100.tiff rename to Data/Input/ResetMarginInput100x100.tiff diff --git a/Modules/Applications/AppImageUtils/app/CMakeLists.txt b/Modules/Applications/AppImageUtils/app/CMakeLists.txt index f1b82f4031..626dd520ec 100644 --- a/Modules/Applications/AppImageUtils/app/CMakeLists.txt +++ b/Modules/Applications/AppImageUtils/app/CMakeLists.txt @@ -94,8 +94,8 @@ OTB_CREATE_APPLICATION( LINK_LIBRARIES ${${otb-module}_LIBRARIES}) OTB_CREATE_APPLICATION( - NAME ClampROI - SOURCES otbClampROI.cxx + NAME ResetMargin + SOURCES otbResetMargin.cxx LINK_LIBRARIES ${${otb-module}_LIBRARIES}) OTB_CREATE_APPLICATION( diff --git a/Modules/Applications/AppImageUtils/app/otbClampROI.cxx b/Modules/Applications/AppImageUtils/app/otbResetMargin.cxx similarity index 88% rename from Modules/Applications/AppImageUtils/app/otbClampROI.cxx rename to Modules/Applications/AppImageUtils/app/otbResetMargin.cxx index 74bca802d1..b3e7aced60 100644 --- a/Modules/Applications/AppImageUtils/app/otbClampROI.cxx +++ b/Modules/Applications/AppImageUtils/app/otbResetMargin.cxx @@ -18,7 +18,7 @@ * limitations under the License. */ -#include "otbClampROIFilter.h" +#include "otbResetMarginFilter.h" #include "otbWrapperApplication.h" #include "otbWrapperApplicationFactory.h" @@ -39,21 +39,21 @@ namespace Wrapper * \author Luc Hermitte (CS Group) * \copyright CNES */ -class ClampROI : public Application +class ResetMargin : public Application { public: - using Self = ClampROI; + using Self = ResetMargin; using Pointer = itk::SmartPointer; itkNewMacro(Self); - itkTypeMacro(ClampROI, otb::Wrapper::Application); + itkTypeMacro(ResetMargin, otb::Wrapper::Application); private: void DoInit() override { - SetName("ClampROI"); + SetName("ResetMargin"); - SetDescription("This is the ClampROI application"); + SetDescription("This is the ResetMargin application"); SetDocLongDescription( "This application is similar to ExtractROI in the sense it extracts a Region of Interrest.\n" "However, the region outside of the ROI isn't trimmed, but set to 0.\n" @@ -94,11 +94,11 @@ private: AddRAMParameter(); - SetDocExampleParameterValue("in", "ClampROIInput100x100.tiff"); + SetDocExampleParameterValue("in", "ResetMarginInput100x100.tiff"); SetDocExampleParameterValue("threshold.x", "10"); SetDocExampleParameterValue("threshold.y.start", "12"); SetDocExampleParameterValue("threshold.y.end", "25"); - SetDocExampleParameterValue("out", "ClampROI.tiff"); + SetDocExampleParameterValue("out", "ResetMargin.tiff"); SetOfficialDocLink(); } @@ -117,9 +117,9 @@ private: if (thrYbot < 0) itkExceptionMacro("The bottom line threshold is expected to be positive"); if (thrX == 0 && thrYtop == 0 && thrYbot == 0) - itkExceptionMacro("Don't use ClampROI to clamp nothing!"); + itkExceptionMacro("Don't use ResetMargin to clamp nothing!"); - auto filter = ClampROIFilter::New(); + auto filter = ResetMarginFilter::New(); assert(thrX >= 0); assert(thrYtop >= 0); assert(thrYbot >= 0); @@ -137,4 +137,4 @@ private: } // otb::Wrapper namespace } // otb namespace -OTB_APPLICATION_EXPORT(otb::Wrapper::ClampROI) +OTB_APPLICATION_EXPORT(otb::Wrapper::ResetMargin) diff --git a/Modules/Applications/AppImageUtils/test/CMakeLists.txt b/Modules/Applications/AppImageUtils/test/CMakeLists.txt index 674fdb043a..65db5e506a 100644 --- a/Modules/Applications/AppImageUtils/test/CMakeLists.txt +++ b/Modules/Applications/AppImageUtils/test/CMakeLists.txt @@ -121,16 +121,16 @@ otb_test_application(NAME apTvUtExtractROIExtentFitVect ${TEMP}/apTvUtExtractROIExtentFitVect.tif) #----------- Clamp ROI tests ---------------- -otb_test_application(NAME apTvUtClampROI - APP ClampROI - OPTIONS -in ${INPUTDATA}/ClampROIInput100x100.tiff - -out ${TEMP}/apTvUtClampROI.tif +otb_test_application(NAME apTvUtResetMargin + APP ResetMargin + OPTIONS -in ${INPUTDATA}/ResetMarginInput100x100.tiff + -out ${TEMP}/apTvUtResetMargin.tif -threshold.x 10 -threshold.y.start 12 -threshold.y.end 25 VALID --compare-image ${NOTOL} - ${OTBAPP_BASELINE}/ClampROIBaseline100x100.tiff - ${TEMP}/apTvUtClampROI.tif) + ${OTBAPP_BASELINE}/ResetMarginBaseline100x100.tiff + ${TEMP}/apTvUtResetMargin.tif) #----------- Rescale TESTS ---------------- otb_test_application(NAME apTvUtRescaleTest diff --git a/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.h b/Modules/Filtering/ImageManipulation/include/otbResetMarginFilter.h similarity index 92% rename from Modules/Filtering/ImageManipulation/include/otbClampROIFilter.h rename to Modules/Filtering/ImageManipulation/include/otbResetMarginFilter.h index 807675349a..1619aaf036 100644 --- a/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.h +++ b/Modules/Filtering/ImageManipulation/include/otbResetMarginFilter.h @@ -18,8 +18,8 @@ * limitations under the License. */ -#ifndef otbClampROIFilter_h -#define otbClampROIFilter_h +#ifndef otbResetMarginFilter_h +#define otbResetMarginFilter_h #include "itkImageToImageFilter.h" @@ -40,7 +40,7 @@ namespace otb * \copyright CNES */ template -class ClampROIFilter : public itk::ImageToImageFilter +class ResetMarginFilter : public itk::ImageToImageFilter { public: @@ -57,7 +57,7 @@ public: //@} /**\name Standard class typedefs */ //@{ - using Self = ClampROIFilter; + using Self = ResetMarginFilter; using Superclass = itk::ImageToImageFilter; using Pointer = itk::SmartPointer; using ConstPointer = itk::SmartPointer; @@ -67,7 +67,7 @@ public: itkNewMacro(Self); /** Run-time type information (and related methods). */ - itkTypeMacro(ClampROIFilter, unused); + itkTypeMacro(ResetMarginFilter, unused); /**\name Image typedef support */ //@{ @@ -107,12 +107,12 @@ public: protected: /// Hidden constructor - ClampROIFilter() = default; + ResetMarginFilter() = default; InputImageType * GetInputImage() { return const_cast(this->GetInput()); } InputImageType const* GetInputImage() const { return this->GetInput(); } - /** otbClampROIFilter doesn't need an input requested region as large as the + /** otbResetMarginFilter doesn't need an input requested region as large as the * output requested region. * \sa ImageToImageFilter::GenerateInputRequestedRegion() */ @@ -147,7 +147,7 @@ private: } // otb namespace #ifndef OTB_MANUAL_INSTANTIATION -#include "otbClampROIFilter.hxx" +#include "otbResetMarginFilter.hxx" #endif -#endif // otbClampROIFilter_h +#endif // otbResetMarginFilter_h diff --git a/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx b/Modules/Filtering/ImageManipulation/include/otbResetMarginFilter.hxx similarity index 97% rename from Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx rename to Modules/Filtering/ImageManipulation/include/otbResetMarginFilter.hxx index 7e893a37c7..0c35e1ad67 100644 --- a/Modules/Filtering/ImageManipulation/include/otbClampROIFilter.hxx +++ b/Modules/Filtering/ImageManipulation/include/otbResetMarginFilter.hxx @@ -18,10 +18,10 @@ * limitations under the License. */ -#ifndef otbClampROIFilter_hxx -#define otbClampROIFilter_hxx +#ifndef otbResetMarginFilter_hxx +#define otbResetMarginFilter_hxx -#include "otbClampROIFilter.h" +#include "otbResetMarginFilter.h" #include "otbInterval.h" #include "otbMacro.h" #include "otbLogHelpers.h" @@ -45,7 +45,7 @@ namespace otb template void -ClampROIFilter +ResetMarginFilter ::ThreadedGenerateData( OutputImageRegionType const& outputRegionForThread, itk::ThreadIdType threadId) @@ -157,8 +157,8 @@ ClampROIFilter } template -typename ClampROIFilter::InputImageRegionType -ClampROIFilter +typename ResetMarginFilter::InputImageRegionType +ResetMarginFilter ::OutputRegionToInputRegion(OutputImageRegionType const& srcRegion) { auto const* output = this->GetOutput(); @@ -211,5 +211,5 @@ ClampROIFilter } // otb namespace -#endif // otbClampROIFilter_hxx +#endif // otbResetMarginFilter_hxx -- GitLab