2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * @author Jacques-Olivier Lachaud (\c jacques-olivier.lachaud@univ-savoie.fr )
20 * Laboratory of Mathematics (CNRS, UMR 5127), University of Savoie, France
21 * @author Marion Foare (\c marion.foare@univ-savoie.fr )
22 * Laboratory of Mathematics (CNRS, UMR 5127), University of Savoie, France
26 * Implementation of inline methods defined in ATu2v0.h
28 * This file is part of the DGtal library.
32//////////////////////////////////////////////////////////////////////////////
34//////////////////////////////////////////////////////////////////////////////
36///////////////////////////////////////////////////////////////////////////////
37// IMPLEMENTATION of inline methods.
38///////////////////////////////////////////////////////////////////////////////
40///////////////////////////////////////////////////////////////////////////////
41// ----------------------- Standard services ------------------------------
42template <typename TKSpace, typename TLinearAlgebra>
43DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
46 M01( calculus ), M12( calculus ), primal_AD2( calculus ),
47 v0( calculus ), former_v0( calculus ),
48 alpha_Id2( calculus ), left_V0( calculus ),
49 l_1_over_4( calculus ), l_1_over_4e( calculus ),
50 l_1_over_4e_Id0( calculus ),
51 metric_average( false )
54template <typename TKSpace, typename TLinearAlgebra>
56DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
57init( Clone<KSpace> aKSpace )
59 Base::init( aKSpace );
60 if ( verbose > 0 ) trace.beginBlock( "Initialize DEC specific operators" );
61 if ( verbose > 1 ) trace.info() << "M01" << std::endl;
62 M01 = calculus.template derivative<0, PRIMAL>();
63 M01.myContainer = .5 * M01.myContainer.cwiseAbs();
64 if ( verbose > 1 ) trace.info() << "M12" << std::endl;
65 M12 = calculus.template derivative<1, PRIMAL>();
66 M12.myContainer = .25 * M12.myContainer.cwiseAbs();
67 if ( verbose > 1 ) trace.info() << "primal_AD2" << std::endl;
68 primal_AD2 = calculus.template antiderivative<2,PRIMAL>();
69 if ( verbose > 1 ) trace.info() << "v0" << std::endl;
70 v0 = KForm<Calculus, 0, PRIMAL>::ones( calculus );
71 if ( verbose > 0 ) trace.endBlock();
74//-----------------------------------------------------------------------------
75template <typename TKSpace, typename TLinearAlgebra>
76template <typename Image, typename Function>
78DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
79addInput( const Image& image,
83 if ( perfect_data ) i2.push_back( PrimalForm2( calculus ) );
84 else g2.push_back( PrimalForm2( calculus ) );
85 PrimalForm2& g = perfect_data ? i2.back() : g2.back();
86 const KSpace& K = calculus.myKSpace;
87 for ( Index index = 0; index < g.myContainer.rows(); index++)
89 SCell cell = g.getSCell( index );
90 g.myContainer( index ) = f( image( K.sCoords( cell ) ) );
94//-----------------------------------------------------------------------------
95template <typename TKSpace, typename TLinearAlgebra>
96typename DGtal::ATu2v0<TKSpace, TLinearAlgebra>::Scalar
97DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
101 for ( Dimension i = 0; i < i2.size(); ++i )
104 const PrimalForm2 u_minus_i_snr = u2[ i ] - i2[ i ];
105 for ( Index j = 0; j < u_minus_i_snr.length(); ++j )
106 MSEi += u_minus_i_snr.myContainer( j ) * u_minus_i_snr.myContainer( j );
107 MSE += MSEi / (Scalar) u_minus_i_snr.length();
110 return 10.0 * log10(1.0 / MSE);
113//-----------------------------------------------------------------------------
114template <typename TKSpace, typename TLinearAlgebra>
116DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
117setMetricAverage( bool average )
119 metric_average = average;
122//-----------------------------------------------------------------------------
123template <typename TKSpace, typename TLinearAlgebra>
125DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
126setAlpha( Scalar _alpha )
128 ASSERT( _alpha >= 0.0 );
130 // Building alpha_Id2
131 alpha_Id2 = _alpha * calculus.template identity<2, PRIMAL>();
133 for ( unsigned int i = 0; i < g2.size(); i++ )
134 alpha_g2.push_back( alpha_Id2 * g2[ i ] );
137//-----------------------------------------------------------------------------
138template <typename TKSpace, typename TLinearAlgebra>
140DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
141setAlpha( Scalar _alpha, const PrimalForm2& m )
143 ASSERT( _alpha >= 0.0 );
145 // Building alpha_Id0
146 alpha_Id2 = _alpha * functions::dec::diagonal( m ) * calculus.template identity<2, PRIMAL>();
148 for ( unsigned int i = 0; i < g2.size(); i++ )
149 alpha_g2.push_back( alpha_Id2 * g2[ i ] );
152//-----------------------------------------------------------------------------
153template <typename TKSpace, typename TLinearAlgebra>
155DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
156setLambda( Scalar _lambda )
158 ASSERT( _lambda >= 0.0 );
160 if ( metric_average )
161 l_1_over_4 = (lambda / 4.0 )
162 * M01.transpose() * M12.transpose()
164 * KForm< Calculus, 0, PRIMAL >::ones( calculus );
166 l_1_over_4 = (lambda / 4.0 )
167 * KForm< Calculus, 0, PRIMAL >::ones( calculus );
170//-----------------------------------------------------------------------------
171template <typename TKSpace, typename TLinearAlgebra>
173DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
174setEpsilon( Scalar _epsilon )
176 ASSERT( _epsilon > 0.0 );
178 if ( metric_average )
179 left_V0 = ( lambda/(4.0*epsilon) )
180 * M01.transpose() * M12.transpose()
182 + (lambda*epsilon) * D0.transpose() * D0;
184 left_V0 = ( lambda/(4.0*epsilon) )
185 * calculus.template identity<0, PRIMAL>()
186 + (lambda*epsilon) * D0.transpose() * D0;
187 l_1_over_4e = (1.0/epsilon) * l_1_over_4;
190//-----------------------------------------------------------------------------
191template <typename TKSpace, typename TLinearAlgebra>
193DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
199//-----------------------------------------------------------------------------
200template <typename TKSpace, typename TLinearAlgebra>
202DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
203setUFromInputAndMask()
206 for ( int i = 0; i < u2.size(); ++i )
208 const Index nb = u2[ i ].length();
209 for ( Index index = 0; index < nb; index++)
211 if ( alpha_g2[ i ].myContainer( index ) == 0.0 )
212 u2[ i ].myContainer( index ) = ((double) rand()) / (double) RAND_MAX;
217//-----------------------------------------------------------------------------
218template <typename TKSpace, typename TLinearAlgebra>
220DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
223 if ( verbose > 0 ) trace.beginBlock("Solving for u");
224 if ( verbose > 1 ) trace.info() << "- building matrix M : = alpha_Id2 - tB'_Diag(M01 v)^2_B'" << std::endl;
226 const PrimalIdentity1 diag_Mv_squared = functions::dec::squaredDiagonal( M01 * v0 );
227 // JOL: clarify sign below.
228 const PrimalIdentity2 M = alpha_Id2
229 + primal_AD2.transpose() * diag_Mv_squared * primal_AD2;
230 if ( verbose > 1 ) trace.info() << "- prefactoring matrix M" << std::endl;
231 solver_u.compute( M );
233 for ( Dimension i = 0; i < u2.size(); ++i )
235 if ( verbose > 1 ) trace.info() << "- solving M u[" << i << "] = alpha g[" << i << "]" << std::endl;
236 u2[ i ] = solver_u.solve( alpha_g2[ i ] );
237 if ( verbose > 1 ) trace.info() << ( solver_u.isValid() ? "=> OK" : "ERROR" ) << " " << solver_u.myLinearAlgebraSolver.info() << std::endl;
238 ok = ok && solver_u.isValid();
240 if ( verbose > 0 ) trace.endBlock();
244//-----------------------------------------------------------------------------
245template <typename TKSpace, typename TLinearAlgebra>
247DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
251 if ( verbose > 0 ) trace.beginBlock("Solving for v");
252 if ( verbose > 1 ) trace.info() << "- building matrix N := l/4e Id0 + le A tA + tM01 sum Diag(B' u_i)^2 M01" << std::endl;
254 PrimalForm1 squared_norm_D_u2 = PrimalForm1::zeros(calculus);
256 PrimalIdentity1 U2 = functions::dec::squaredDiagonal( primal_AD2 * u2[ 0 ] );
257 for ( Dimension i = 1; i < u2.size(); ++i )
258 U2.myContainer += functions::dec::squaredDiagonal( primal_AD2 * u2[ i ] ).myContainer;
259 const PrimalIdentity0 N = left_V0 + M01.transpose() * U2 * M01;
261 typedef typename PrimalIdentity0::Container Matrix;
262 const Matrix & M = N.myContainer;
264 for (int k = 0; k < M.outerSize(); ++k)
265 for ( typename Matrix::InnerIterator it( M, k ); it; ++it )
266 if ( ( verbose > 3 ) || ( it.row() == it.col() ) )
267 trace.info() << "[" << it.row() << "," << it.col() << "] = " << it.value() << std::endl;
268 if ( verbose > 1 ) trace.info() << "- prefactoring matrix N" << std::endl;
269 solver_v.compute( N );
270 if ( verbose > 1 ) trace.info() << "- solving N v = l/4e 1" << std::endl;
271 v0 = solver_v.solve( l_1_over_4e );
272 if ( verbose > 1 ) trace.info() << ( solver_v.isValid() ? "OK" : "ERROR" )
273 << " " << solver_v.myLinearAlgebraSolver.info()
275 if ( verbose > 0 ) trace.endBlock();
276 return solver_v.isValid();
279//-----------------------------------------------------------------------------
280template <typename TKSpace, typename TLinearAlgebra>
281typename DGtal::ATu2v0<TKSpace, TLinearAlgebra>::Scalar
282DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
285 if ( verbose > 0 ) trace.beginBlock( "Compute variation of v.");
289 for ( Index index = 0; index < size0(); index++)
291 delta_v_loo = std::max( delta_v_loo, std::fabs( v0.myContainer( index )
292 - former_v0.myContainer( index ) ) );
293 delta_v_l2 += ( v0.myContainer( index ) - former_v0.myContainer( index ) )
294 * ( v0.myContainer( index ) - former_v0.myContainer( index ) );
295 delta_v_l1 += fabs( v0.myContainer( index )
296 - former_v0.myContainer( index ) );
298 delta_v_l1 /= size0();
299 delta_v_l2 = sqrt( delta_v_l2 / size0() );
301 trace.info() << "Variation |v^k+1 - v^k|_oo = " << delta_v_loo << std::endl;
302 trace.info() << "Variation |v^k+1 - v^k|_2 = " << delta_v_l2 << std::endl;
303 trace.info() << "Variation |v^k+1 - v^k|_1 = " << delta_v_l1 << std::endl;
305 if ( verbose > 0 ) trace.endBlock();
309//-----------------------------------------------------------------------------
310template <typename TKSpace, typename TLinearAlgebra>
311typename DGtal::ATu2v0<TKSpace, TLinearAlgebra>::Scalar
312DGtal::ATu2v0<TKSpace, TLinearAlgebra>::
315 if ( verbose > 0 ) trace.beginBlock("Checking v");
319 for ( Index index = 0; index < size0(); index++)
321 Scalar val = v0.myContainer( index );
322 m1 = std::min( m1, val );
323 m2 = std::max( m2, val );
327 trace.info() << "1-form v: min=" << m1 << " avg=" << ( ma / size0() )
328 << " max=" << m2 << std::endl;
329 // for ( Index index = 0; index < size1(); index++)
330 // v0.myContainer( index ) = std::min( std::max(v0.myContainer( index ), 0.0) , 1.0 );
331 if ( verbose > 0 ) trace.endBlock();
332 return std::max( std::fabs( m1 ), std::fabs( m2 - 1.0 ) );
336///////////////////////////////////////////////////////////////////////////////
337// Interface - public :
340 * Writes/Displays the object on an output stream.
341 * @param out the output stream where the object is written.
343template <typename TKSpace, typename TLinearAlgebra>
346DGtal::ATu2v0<TKSpace, TLinearAlgebra>::selfDisplay ( std::ostream & out ) const
348 out << "[ ATu2v0 #g=" << g2.size() << " dec=" << calculus << " ]";
352 * Checks the validity/consistency of the object.
353 * @return 'true' if the object is valid, 'false' otherwise.
355template <typename TKSpace, typename TLinearAlgebra>
358DGtal::ATu2v0<TKSpace, TLinearAlgebra>::isValid() const
365///////////////////////////////////////////////////////////////////////////////
366// Implementation of inline functions //
368template <typename TKSpace, typename TLinearAlgebra>
371DGtal::operator<< ( std::ostream & out,
372 const ATu2v0<TKSpace, TLinearAlgebra> & object )
374 object.selfDisplay( out );
379///////////////////////////////////////////////////////////////////////////////