OTB  9.0.0
Orfeo Toolbox
otbBayesianFusionFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1999-2011 Insight Software Consortium
3  * Copyright (C) 2005-2022 Centre National d'Etudes Spatiales (CNES)
4  *
5  * This file is part of Orfeo Toolbox
6  *
7  * https://www.orfeo-toolbox.org/
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 #ifndef otbBayesianFusionFilter_hxx
23 #define otbBayesianFusionFilter_hxx
24 
26 
27 namespace otb
28 {
29 
30 template <class TInputMultiSpectralImage, class TInputMultiSpectralInterpImage, class TInputPanchroImage, class TOutputImage>
32 {
33  Superclass::Modified();
34  m_StatisticsHaveBeenGenerated = false;
35 }
36 
37 template <class TInputMultiSpectralImage, class TInputMultiSpectralInterpImage, class TInputPanchroImage, class TOutputImage>
39 {
40  if (!m_StatisticsHaveBeenGenerated)
41  {
42  this->ComputeInternalStatistics();
43  m_StatisticsHaveBeenGenerated = true;
44  }
45 }
46 
47 template <class TInputMultiSpectralImage, class TInputMultiSpectralInterpImage, class TInputPanchroImage, class TOutputImage>
49 {
50  OutputImageRegionType msiRequestedRegion = this->GetMultiSpectInterp()->GetRequestedRegion();
51  OutputImageRegionType msRequestedRegion = this->GetMultiSpect()->GetRequestedRegion();
52  OutputImageRegionType panchroRequestedRegion = this->GetPanchro()->GetRequestedRegion();
53 
54  // Allocate output
55  typename OutputImageType::Pointer output = this->GetOutput();
56  typename InputMultiSpectralImageType::Pointer multiSpec = const_cast<InputMultiSpectralImageType*>(this->GetMultiSpect());
57  typename InputMultiSpectralInterpImageType::Pointer multiSpecInterp = const_cast<InputMultiSpectralInterpImageType*>(this->GetMultiSpectInterp());
58  typename InputPanchroImageType::Pointer panchro = const_cast<InputPanchroImageType*>(this->GetPanchro());
59 
61  m_Beta.SetSize(multiSpecInterp->GetNumberOfComponentsPerPixel() + 1, 1);
62  m_Beta.Fill(itk::NumericTraits<InputMultiSpectralInterpRealType>::Zero);
64 
65  m_CovarianceMatrix.SetSize(multiSpecInterp->GetNumberOfComponentsPerPixel(), multiSpecInterp->GetNumberOfComponentsPerPixel());
66  m_CovarianceMatrix.Fill(itk::NumericTraits<InputMultiSpectralInterpRealType>::Zero);
67 
68  m_CovarianceInvMatrix.SetSize(multiSpecInterp->GetNumberOfComponentsPerPixel(), multiSpecInterp->GetNumberOfComponentsPerPixel());
69  m_CovarianceInvMatrix.Fill(itk::NumericTraits<InputMultiSpectralInterpRealType>::Zero);
70 
71  m_Vcondopt.SetSize(multiSpecInterp->GetNumberOfComponentsPerPixel(), multiSpecInterp->GetNumberOfComponentsPerPixel());
72  m_Vcondopt.Fill(itk::NumericTraits<InputMultiSpectralInterpRealType>::Zero);
74  typename StreamingStatisticsVectorImageFilterType::Pointer covComputefilter = StreamingStatisticsVectorImageFilterType::New();
75 
76  covComputefilter->SetInput(multiSpecInterp);
77  covComputefilter->Update();
78 
79  m_CovarianceMatrix = covComputefilter->GetCovariance();
80  otbMsgDebugMacro(<< "Covariance: " << m_CovarianceMatrix);
81 
82  m_CovarianceInvMatrix = m_CovarianceMatrix.GetInverse();
84  // MatrixTransform only support vectorimage input
85  typename CasterType::Pointer caster = CasterType::New();
86  caster->SetInput(panchro);
87  // caster->Update();
88  // Compute the transpose multispectral image multiplied by itself
89  typename MSTransposeMSType::Pointer msTransposeMs = MSTransposeMSType::New();
90  // Compute the transpose multispectral image multiplied by the panchromatic one
91  typename MSTransposeMSType::Pointer msTransposePan = MSTransposeMSType::New();
92  // Add a dimension filled with ones to the images
93  msTransposeMs->SetUsePadFirstInput(true);
94  msTransposeMs->SetUsePadSecondInput(true);
95  msTransposePan->SetUsePadFirstInput(true);
97 
98  msTransposeMs->SetFirstInput(multiSpec);
99  msTransposeMs->SetSecondInput(multiSpec);
100 
101  msTransposePan->SetFirstInput(multiSpec);
102  msTransposePan->SetSecondInput(caster->GetOutput());
103 
104  msTransposeMs->Update();
105  otbMsgDebugMacro(<< "MsTMs: " << msTransposeMs->GetResultOutput()->Get());
106  msTransposePan->Update();
107  otbMsgDebugMacro(<< "MsTPan: " << msTransposePan->GetResultOutput()->Get());
108 
109  MatrixType temp;
110  temp = msTransposeMs->GetResultOutput()->Get().GetInverse();
111  m_Beta = temp * msTransposePan->GetResultOutput()->Get();
112 
113  // S computation : quadratique mean of the regression residue
114  // Compute the transpose panchromatic image multiplied by itself
115  typename MSTransposeMSType::Pointer panTransposePan = MSTransposeMSType::New();
116  panTransposePan->SetFirstInput(caster->GetOutput());
117  panTransposePan->SetSecondInput(caster->GetOutput());
118  panTransposePan->Update();
119  otbMsgDebugMacro(<< "PanTPan: " << msTransposePan->GetResultOutput()->Get());
120  MatrixType S, tempS, tempS2;
121  S = panTransposePan->GetResultOutput()->Get();
122  tempS = msTransposePan->GetResultOutput()->Get().GetTranspose();
123  tempS = tempS * m_Beta;
124 
129  if ((S.Rows() != tempS.Rows()) || (S.Cols() != tempS.Cols()))
130  {
131  itkExceptionMacro(<< "Matrix with size (" << S.Rows() << "," << S.Cols() << ") cannot be subtracted from matrix with size (" << tempS.Rows() << ","
132  << tempS.Cols() << " )");
133  }
134  for (unsigned int r = 0; r < S.Rows(); ++r)
135  {
136  for (unsigned int c = 0; c < S.Cols(); ++c)
137  {
138  S(r, c) -= tempS(r, c);
139  }
140  }
141 
142 /**** END TODO ****/
143 
144  tempS = m_Beta.GetTranspose();
145  tempS2 = msTransposePan->GetResultOutput()->Get();
146  tempS = tempS * tempS2;
151  if ((S.Rows() != tempS.Rows()) || (S.Cols() != tempS.Cols()))
152  {
153  itkExceptionMacro(<< "Matrix with size (" << S.Rows() << "," << S.Cols() << ") cannot be subtracted from matrix with size (" << tempS.Rows() << ","
154  << tempS.Cols() << " )");
155  }
156  for (unsigned int r = 0; r < S.Rows(); ++r)
157  {
158  for (unsigned int c = 0; c < S.Cols(); ++c)
159  {
160  S(r, c) -= tempS(r, c);
161  }
162  }
163 
164 /**** END TODO ****/
165 
166  MatrixType xxT, xxTb, xxTbT, xxTbTb;
167  xxT = msTransposeMs->GetResultOutput()->Get().GetTranspose();
168  xxTb = xxT * m_Beta;
169  xxTbT = xxTb.GetTranspose();
170  xxTbTb = xxTbT * m_Beta;
175  if ((S.Rows() != xxTbTb.Rows()) || (S.Cols() != xxTbTb.Cols()))
176  {
177  itkExceptionMacro(<< "Matrix with size (" << S.Rows() << "," << S.Cols() << ") cannot be subtracted from matrix with size (" << xxTbTb.Rows() << ","
178  << xxTbTb.Cols() << " )");
179  }
181 
182  for (unsigned int r = 0; r < S.Rows(); ++r)
183  {
184  for (unsigned int c = 0; c < S.Cols(); ++c)
185  {
186  S(r, c) += xxTbTb(r, c);
187  }
188  }
189 /**** END TODO ****/
190 
191  unsigned int size1 = multiSpec->GetLargestPossibleRegion().GetSize()[0] * multiSpec->GetLargestPossibleRegion().GetSize()[1];
192  unsigned int size2 = multiSpec->GetNumberOfComponentsPerPixel() + 1;
193  m_S = S(0, 0);
194  m_S /= static_cast<float>(size1 - size2);
195 
196  // cutBeta is the N-1 last m_Beta element matrix.
197  // varPan contains transpose(cutBeta)*cutBeta/S
198  MatrixType varPan, cutBeta;
199  varPan.SetSize(multiSpecInterp->GetNumberOfComponentsPerPixel(), 1);
200  varPan.Fill(itk::NumericTraits<InputMultiSpectralInterpRealType>::Zero);
201  cutBeta.SetSize(multiSpecInterp->GetNumberOfComponentsPerPixel(), 1);
202  cutBeta.Fill(itk::NumericTraits<InputMultiSpectralInterpRealType>::Zero);
203  // Take the N-1 m_Beta last elements
204  for (unsigned int r = 1; r < m_Beta.Rows(); ++r)
205  {
206  cutBeta(r - 1, 0) = m_Beta(r, 0);
207  }
208  varPan = cutBeta;
209 
210  MatrixType tempvarPan;
211  tempvarPan = varPan.GetTranspose();
212  varPan *= tempvarPan;
213  varPan /= m_S;
214  // Compute the optimization matrix : m_Vcondopt
215  // eye is the identical matrix which size is the number of components of the multispectral image
216  MatrixType eye;
217  eye.SetSize(multiSpecInterp->GetNumberOfComponentsPerPixel(), multiSpecInterp->GetNumberOfComponentsPerPixel());
218  eye.Fill(itk::NumericTraits<InputMultiSpectralInterpRealType>::Zero);
219  for (unsigned int r = 1; r < eye.Rows(); ++r)
220  {
221  eye(r, r) = std::pow(10., -12.);
222  }
223 
228  if ((m_Vcondopt.Rows() != varPan.Rows()) || (m_Vcondopt.Cols() != varPan.Cols()) || (m_Vcondopt.Rows() != m_CovarianceInvMatrix.Rows()) ||
229  (m_Vcondopt.Cols() != m_CovarianceInvMatrix.Cols()))
230  {
231  itkExceptionMacro(<< "Matrix with size (" << m_Vcondopt.Rows() << "," << m_Vcondopt.Cols() << ") cannot be subtracted from matrix with size ("
232  << varPan.Rows() << "," << varPan.Cols() << " ) or ( " << m_CovarianceInvMatrix.Rows() << "," << m_CovarianceInvMatrix.Cols() << ")");
233  }
234  for (unsigned int r = 0; r < m_Vcondopt.Rows(); ++r)
235  {
236  for (unsigned int c = 0; c < m_Vcondopt.Cols(); ++c)
237  {
238  m_Vcondopt(r, c) = 2 * m_Lambda * varPan(r, c) + 2 * m_CovarianceInvMatrix(r, c) * (1 - m_Lambda) + eye(r, c);
239  }
240  }
241 
243  m_Vcondopt = m_Vcondopt.GetInverse();
244  // Functor initialization
245  this->GetModifiableFunctor().SetVcondopt(m_Vcondopt);
246  this->GetModifiableFunctor().SetBeta(cutBeta);
247  this->GetModifiableFunctor().SetAlpha(m_Beta(0, 0));
248  this->GetModifiableFunctor().SetCovarianceInvMatrix(m_CovarianceInvMatrix);
249  this->GetModifiableFunctor().SetLambda(m_Lambda);
250  this->GetModifiableFunctor().SetS(m_S);
252 
253  // Restore the previous buffered data
254  multiSpecInterp->SetRequestedRegion(msiRequestedRegion);
255  multiSpecInterp->PropagateRequestedRegion();
256  multiSpecInterp->UpdateOutputData();
257 
258  multiSpec->SetRequestedRegion(msRequestedRegion);
259  multiSpec->PropagateRequestedRegion();
260  multiSpec->UpdateOutputData();
261 
262  panchro->SetRequestedRegion(panchroRequestedRegion);
263  panchro->PropagateRequestedRegion();
264  panchro->UpdateOutputData();
265 }
266 } // end namespace otb
267 
268 #endif
otb::BayesianFusionFilter::OutputImageRegionType
OutputImageType::RegionType OutputImageRegionType
Definition: otbBayesianFusionFilter.h:241
otbBayesianFusionFilter.h
otb::StreamingStatisticsVectorImageFilter::Pointer
itk::SmartPointer< Self > Pointer
Definition: otbStreamingStatisticsVectorImageFilter.h:304
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::ImageToVectorImageCastFilter::Pointer
itk::SmartPointer< Self > Pointer
Definition: otbImageToVectorImageCastFilter.h:89
otb::BayesianFusionFilter::InputMultiSpectralInterpImageType
TInputMultiSpectralInterpImage InputMultiSpectralInterpImageType
Definition: otbBayesianFusionFilter.h:207
otb::BayesianFusionFilter::Modified
void Modified(void) const override
Definition: otbBayesianFusionFilter.hxx:31
otb::BayesianFusionFilter::BeforeThreadedGenerateData
void BeforeThreadedGenerateData() override
Definition: otbBayesianFusionFilter.hxx:38
otb::BayesianFusionFilter::ComputeInternalStatistics
void ComputeInternalStatistics(void)
Definition: otbBayesianFusionFilter.hxx:48
otb::BayesianFusionFilter::InputMultiSpectralImageType
TInputMultiSpectralImage InputMultiSpectralImageType
Definition: otbBayesianFusionFilter.h:206
otb::BayesianFusionFilter::MatrixType
StreamingStatisticsVectorImageFilterType::MatrixType MatrixType
Definition: otbBayesianFusionFilter.h:248
otbMsgDebugMacro
#define otbMsgDebugMacro(x)
Definition: otbMacro.h:62
otb::BayesianFusionFilter::InputPanchroImageType
TInputPanchroImage InputPanchroImageType
Definition: otbBayesianFusionFilter.h:208
otb::StreamingMatrixTransposeMatrixImageFilter::Pointer
itk::SmartPointer< Self > Pointer
Definition: otbStreamingMatrixTransposeMatrixImageFilter.h:223