OTB  10.0.0
Orfeo Toolbox
otbStreamingFeatherMosaicFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1999-2011 Insight Software Consortium
3  * Copyright (C) 2005-2024 Centre National d'Etudes Spatiales (CNES)
4  * Copyright (C) 2016-2019 IRSTEA
5  *
6  * This file is part of Orfeo Toolbox
7  *
8  * https://www.orfeo-toolbox.org/
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22 #ifndef __StreamingFeatherMosaicFilter_hxx
23 #define __StreamingFeatherMosaicFilter_hxx
24 
26 
27 namespace otb
28 {
29 
30 template <class TInputImage, class TOutputImage, class TDistanceImage, class TInternalValueType>
32 {
33  m_FeatheringTransitionDistance = 500;
34  m_FeatheringSmoothness = 1.5;
35 }
36 
40 template <class TInputImage, class TOutputImage, class TDistanceImage, class TInternalValueType>
42  const OutputImageRegionType& outputRegionForThread)
43 {
44 
45  // Get output pointer
46  OutputImageType* mosaicImage = this->GetOutput();
47 
48  // Get number of used inputs
49  const unsigned int nbOfUsedInputImages = Superclass::GetNumberOfUsedInputImages();
50 
51  // Get number of bands
52  const unsigned int nBands = Superclass::GetNumberOfBands();
53 
54  // Iterate through the thread region
55  IteratorType outputIt(mosaicImage, outputRegionForThread);
56 
57  // Prepare input pointers, interpolators, and valid regions (input images)
58  typename std::vector<InputImageType*> currentImage;
59  typename std::vector<InterpolatorPointerType> interp;
60  Superclass::PrepareImageAccessors(currentImage, interp);
61 
62  // Prepare input pointers, interpolators, and valid regions (distances images)
63  typename std::vector<DistanceImageType*> currentDistanceImage;
64  typename std::vector<DistanceImageInterpolatorPointer> distanceInterpolator;
65  Superclass::PrepareDistanceImageAccessors(currentDistanceImage, distanceInterpolator);
66 
67  // Temporary pixels
68  InternalPixelType interpolatedMathPixel, tempOutputPixel;
69  interpolatedMathPixel.SetSize(nBands);
70  tempOutputPixel.SetSize(nBands);
71 
72  InputImagePixelType interpolatedPixel;
73  InternalValueType pixelValue, distanceImagePixel;
74  bool isDataInCurrentOutputPixel;
75 
76  // Temporary coordinates
77  OutputImagePointType geoPoint;
78 
79  unsigned int band, i;
80 
81  for (outputIt.GoToBegin(); !outputIt.IsAtEnd(); ++outputIt)
82  {
83  // Current pixel --> Geographical point
84  mosaicImage->TransformIndexToPhysicalPoint(outputIt.GetIndex(), geoPoint);
85 
86  // Presence of at least one non-null pixel of the used input images
87  isDataInCurrentOutputPixel = false;
88 
89  // Transition pixels
90  tempOutputPixel.Fill(0.0);
91 
92  // Loop on used input images
93  for (i = 0; i < nbOfUsedInputImages; i++)
94  {
95 
96  // Check if the point is inside the transformed thread region
97  // (i.e. the region in the current input image which match the thread
98  // region)
99  if (interp[i]->IsInsideBuffer(geoPoint))
100  {
101 
102  // Compute the interpolated pixel value
103  interpolatedPixel = interp[i]->Evaluate(geoPoint);
104 
105  // Check that interpolated pixel is not empty
106  if (Superclass::IsPixelNotEmpty(interpolatedPixel))
107  {
108 
109  // Geographical point (current pixel) --> Continuous index (from
110  // current input image)
111  if (distanceInterpolator[i]->IsInsideBuffer(geoPoint))
112  {
113  distanceImagePixel = distanceInterpolator[i]->Evaluate(geoPoint);
114  distanceImagePixel -= Superclass::GetDistanceOffset();
115 
116  // Check that the distance is positive (i.e. we are inside the valid
117  // area of the image)
118  if (distanceImagePixel > 0 || !isDataInCurrentOutputPixel)
119  {
120 
121  // Two possibility: distance < buffer or not
122  InternalValueType coef1, coef2;
123  if (distanceImagePixel < m_FeatheringTransitionDistance && isDataInCurrentOutputPixel)
124  {
125  // Feather the image
126  coef1 = distanceImagePixel / m_FeatheringTransitionDistance;
127  coef1 = vcl_pow(coef1, m_FeatheringSmoothness);
128  coef2 = 1.0 - coef1;
129  }
130  else
131  {
132  // Do not feather, put the image foreground
133  coef1 = 1.0;
134  coef2 = 0.0;
135  }
136 
137  // Average-Weight pixels (current pixel, and temporary pixel)
138  const unsigned int inputImageIndex = Superclass::GetUsedInputImageIndice(i);
139  for (band = 0; band < nBands; band++)
140  {
141  // Cast the interpolated pixel to a internal pixel type
142  interpolatedMathPixel[band] = static_cast<InternalValueType>(interpolatedPixel[band]);
143 
144  // Shift-scale the input pixel value
145  if (this->GetShiftScaleInputImages())
146  {
147  this->ShiftScaleValue(interpolatedMathPixel[band], inputImageIndex, band);
148  }
149 
150  // Average-Weight
151  tempOutputPixel[band] = coef1 * interpolatedMathPixel[band] + coef2 * tempOutputPixel[band];
152 
153  } // loop on pixels band
154 
155  // Update the presence of data for this pixel
156  isDataInCurrentOutputPixel = true;
157 
158  } // Distance value is positive
159 
160  } // Interpolated distance pixel not empty
161 
162  else
163  {
164  itkWarningMacro(<< "Unable to evaluate distance at point " << geoPoint);
165  distanceImagePixel = 0;
166  }
167 
168  } // Interpolated pixel is not empty
169  } // point inside buffer
170  } // next image
171 
172  // Prepare output pixel
173  OutputImagePixelType outputPixel(Superclass::GetNoDataOutputPixel());
174 
175  if (isDataInCurrentOutputPixel)
176  {
177 
178  // Compute output pixel
179  for (band = 0; band < nBands; band++)
180  {
181 
182  // Normalize & cast
183  pixelValue = tempOutputPixel[band];
184  Superclass::NormalizePixelValue(pixelValue);
185  outputPixel[band] = static_cast<OutputImageInternalPixelType>(pixelValue);
186  }
187 
188  } // if data presence
189 
190  // Update output pixel value
191  outputIt.Set(outputPixel);
192 
193  } // next output pixel
194 }
195 
196 } // end namespace gtb
197 
198 #endif
Superclass::InternalPixelType InternalPixelType
Superclass::OutputImagePixelType OutputImagePixelType
Superclass::OutputImagePointType OutputImagePointType
Superclass::OutputImageInternalPixelType OutputImageInternalPixelType
Superclass::InternalValueType InternalValueType
Superclass::InputImagePixelType InputImagePixelType
Superclass::OutputImageRegionType OutputImageRegionType
void DynamicThreadedGenerateData(const OutputImageRegionType &outputRegionForThread) override
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.