motion.cpp

00001 /* ***** BEGIN LICENSE BLOCK *****
00002 *
00003 * $Id: motion.cpp,v 1.2 2005/01/30 05:11:40 gabest Exp $ $Name:  $
00004 *
00005 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006 *
00007 * The contents of this file are subject to the Mozilla Public License
00008 * Version 1.1 (the "License"); you may not use this file except in compliance
00009 * with the License. You may obtain a copy of the License at
00010 * http://www.mozilla.org/MPL/
00011 *
00012 * Software distributed under the License is distributed on an "AS IS" basis,
00013 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
00014 * the specific language governing rights and limitations under the License.
00015 *
00016 * The Original Code is BBC Research and Development code.
00017 *
00018 * The Initial Developer of the Original Code is the British Broadcasting
00019 * Corporation.
00020 * Portions created by the Initial Developer are Copyright (C) 2004.
00021 * All Rights Reserved.
00022 *
00023 * Contributor(s): Thomas Davies (Original Author), Chris Bowley
00024 *
00025 * Alternatively, the contents of this file may be used under the terms of
00026 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
00027 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
00028 * the GPL or the LGPL are applicable instead of those above. If you wish to
00029 * allow use of your version of this file only under the terms of the either
00030 * the GPL or LGPL and not to allow others to use your version of this file
00031 * under the MPL, indicate your decision by deleting the provisions above
00032 * and replace them with the notice and other provisions required by the GPL
00033 * or LGPL. If you do not delete the provisions above, a recipient may use
00034 * your version of this file under the terms of any one of the MPL, the GPL
00035 * or the LGPL.
00036 * ***** END LICENSE BLOCK ***** */
00037 
00038 
00040 //classes and functions for motion estimation and compensation//
00042 
00043 #include <libdirac_common/motion.h>
00044 using namespace dirac;
00045 
00046 #include <cmath>
00047 
00048 using namespace std;
00049 
00050 //Motion vector and Motion Estimation structures//
00052 
00053 MvData::MvData( const int xnumMB, const int ynumMB , 
00054                 const int xnumblocks, const int ynumblocks , const int num_refs ):
00055     m_vectors( Range(1 , num_refs) ),
00056     m_gm_vectors( Range(1 , num_refs) ),
00057     m_modes( ynumblocks , xnumblocks ),
00058     m_dc( 3 ),
00059     m_mb_split( ynumMB , xnumMB ),
00060     m_mb_common( ynumMB , xnumMB ),
00061     m_gm_params( Range(1 , num_refs) )
00062 {
00063 
00064     InitMvData();
00065 }
00066 
00067 MvData::MvData( const int xnumMB , const int ynumMB , const int num_refs ):
00068     m_vectors( Range(1 , num_refs) ),
00069     m_gm_vectors( Range(1 , num_refs) ),
00070     m_modes( 4*ynumMB , 4*xnumMB ),
00071     m_dc( 3 ),
00072     m_mb_split( ynumMB , xnumMB ),
00073     m_mb_common( ynumMB , xnumMB ),
00074     m_gm_params( Range(1 , num_refs) )
00075 {
00076     InitMvData();
00077 }
00078 
00079 void MvData::InitMvData()
00080 {
00081     // Create the arrays of vectors
00082      for ( int i=m_vectors.First() ; i<=m_vectors.Last() ; ++i ){
00083          m_vectors[i] = new MvArray( Mode().LengthY() , Mode().LengthX() );
00084          m_gm_vectors[i] = new MvArray( Mode().LengthY() , Mode().LengthX() );
00085      }
00086 
00087     // create global motion parameter arrays
00088     for ( int i=m_gm_params.First() ; i<=m_gm_params.Last() ; ++i ){
00089          m_gm_params[i] = new OneDArray<float> ( 8 );
00090     }
00091 
00092      // Create the arrays of dc values
00093      for ( int i=0 ; i<3 ; ++i )
00094          m_dc[i] = new TwoDArray<ValueType>( Mode().LengthY() , Mode().LengthX() );
00095 }
00096 
00097 MvData::~MvData()
00098 {
00099    // Delete the arrays of vectors
00100     for ( int i=m_vectors.First() ; i<=m_vectors.Last() ; ++i ){
00101         delete m_vectors[i];
00102         delete m_gm_vectors[i];
00103     }
00104 
00105      // delete array of global motion parameters
00106      for ( int i=m_gm_params.First() ; i<=m_gm_params.Last() ; ++i ){
00107          delete m_gm_params[i];
00108      }
00109 
00110      // Delete the arrays of dc values
00111      for ( int i=0 ; i<3 ; ++i )
00112          delete m_dc[i];
00113 }
00114 
00115 
00116 
00117 MEData::MEData(const int xnumMB , const int ynumMB ,
00118                 const int xnumblocks , const int ynumblocks , const int num_refs ):
00119      MvData( xnumMB , ynumMB , xnumblocks , ynumblocks , num_refs ),
00120      m_pred_costs( Range( 1 , num_refs ) ),
00121      m_intra_costs( ynumblocks , xnumblocks ),
00122      m_bipred_costs( ynumblocks , xnumblocks ),
00123      m_MB_costs( ynumMB , xnumMB ),
00124      m_lambda_map( ynumblocks , xnumblocks ),
00125      m_inliers( Range( 1 , num_refs ) )
00126 {
00127     InitMEData();
00128 }
00129 
00130 MEData::MEData( const int xnumMB , const int ynumMB ,  const int num_refs ):
00131      MvData( xnumMB , ynumMB , num_refs ),
00132      m_pred_costs( Range( 1 , num_refs ) ),
00133      m_intra_costs( 4*ynumMB , 4*xnumMB ),
00134      m_bipred_costs( 4*ynumMB , 4*xnumMB ),
00135      m_MB_costs( ynumMB , xnumMB ),
00136      m_lambda_map( 4*ynumMB , 4*xnumMB ),
00137      m_inliers( Range( 1 , num_refs ) )
00138 {
00139     InitMEData();
00140 
00141 }
00142 
00143 void MEData::InitMEData()
00144 {
00145    // Create the arrays of prediction costs
00146     for ( int i=m_pred_costs.First() ; i<=m_pred_costs.Last() ; ++i )
00147         m_pred_costs[i] = new TwoDArray<MvCostData>( Mode().LengthY() , Mode().LengthX() );
00148 
00149     // Create the arrays of vectors
00150      for ( int i=m_inliers.First() ; i<=m_inliers.Last() ; ++i )
00151          m_inliers[i] = new TwoDArray<int>( Mode().LengthY() , Mode().LengthX() );
00152 }
00153 
00154 void MEData::SetLambdaMap( const int num_refs , const float lambda )
00155 {
00156     TwoDArray<bool> transition_map1( Mode().LengthY() , Mode().LengthX() );
00157     TwoDArray<bool> transition_map2( Mode().LengthY() , Mode().LengthX() );
00158 
00159     FindTransitions( transition_map1 , 1 );
00160 
00161     for ( int j=0 ; j<m_lambda_map.LengthY() ; j++)
00162     {
00163         for ( int i=0 ; i<m_lambda_map.LengthX() ; i++)
00164         {
00165             if ( transition_map1[j][i] )
00166                 m_lambda_map[j][i] = 0.0;
00167             else
00168                 m_lambda_map[j][i] = lambda;
00169             if ( i<4 || j<4 )
00170                 m_lambda_map[j][i] /= 5.0; 
00171         }// i
00172     }// j
00173 
00174     if ( num_refs > 1 )
00175     {
00176         FindTransitions( transition_map2 , 2 );
00177 
00178         for ( int j=0 ; j<m_lambda_map.LengthY() ; j++)
00179         {
00180             for ( int i=0 ; i<m_lambda_map.LengthX() ; i++)
00181             {
00182                 if ( transition_map1[j][i] || transition_map2[j][i] )
00183                     m_lambda_map[j][i] = 0.0;
00184                 else
00185                     m_lambda_map[j][i] = lambda;
00186             }// i
00187         }// j
00188     }
00189 
00190 }
00191 
00192 void MEData::SetLambdaMap( const int level , const TwoDArray<float>& l_map , const float wt )
00193 {
00194 
00195     const int factor = 1<<(2-level);
00196     int xstart , xend , ystart , yend;
00197  
00198     for (int j = 0 ; j<m_lambda_map.LengthY() ; ++j )
00199     {
00200         for (int i = 0 ; i<m_lambda_map.LengthX() ; ++i )
00201         {
00202             xstart = factor * i;
00203             ystart = factor * j;
00204             xend = factor * ( i + 1 );
00205             yend = factor * ( j + 1 );
00206 
00207             m_lambda_map[j][i] = l_map[ystart][xstart];
00208 
00209             for (int q = ystart ; q<yend ; ++q )
00210                 for (int p = xstart ; p<xend ; ++p )
00211                       m_lambda_map[j][i] = std::max( l_map[q][p] , m_lambda_map[j][i] );
00212 
00213            m_lambda_map[j][i] *= wt;
00214 
00215         }// i
00216     }// j
00217 
00218 }
00219 
00220 void MEData::FindTransitions( TwoDArray<bool>& trans_map , const int ref_num )
00221 {
00222     const MvArray& mv_array = Vectors( ref_num );
00223 
00224     // Start with a statistical approach - determine thresholds later
00225 
00226     // Compute mean and standard deviation of local motion vector variance //
00228 
00229     long double total_cost = 0.0;
00230     long double mean_cost;
00231  
00232     // first, mean
00233     for ( int j=0 ; j<mv_array.LengthY() ; ++j )
00234         for ( int i=0 ; i<mv_array.LengthX() ; ++i )
00235             total_cost += PredCosts( ref_num )[j][i].SAD;
00236 
00237     mean_cost = total_cost / 
00238                    static_cast<long double>( mv_array.LengthX()*mv_array.LengthY() );
00239 
00240     // next , Standard Deviation
00241     long double sd_cost = 0.0;
00242     double diff;
00243     
00244     for ( int j=0 ; j<mv_array.LengthY() ; ++j )
00245     {
00246         for ( int i=0 ; i<mv_array.LengthX() ; ++i )
00247         {
00248             diff = PredCosts( ref_num )[j][i].SAD - mean_cost;
00249             diff *= diff;
00250             sd_cost += diff;
00251 
00252         }// i
00253     }// j
00254 
00255     // Get the variance ...
00256     sd_cost /= static_cast<long double>( mv_array.LengthX()*mv_array.LengthY() );
00257 
00258     // ... and then the SD
00259     sd_cost = std::sqrt( sd_cost );
00260 
00261     float threshold = static_cast<float>( mean_cost + 1.5*sd_cost );
00262 
00263     // now go through and mark those that go above the threshold
00264     for ( int j=0 ; j<mv_array.LengthY() ; ++j )
00265         for ( int i=0 ; i<mv_array.LengthX() ; ++i )
00266             trans_map[j][i] = ( PredCosts( ref_num )[j][i].SAD >= threshold )? true : false;
00267 
00268 //
00269     // Next look at motion-vector costs
00270     TwoDArray<double> val_array( mv_array.LengthY() , mv_array.LengthX() );
00271 
00272     // first, mean
00273     total_cost = 0.0;
00274     for ( int i=0 ; i<mv_array.LengthX() ; ++i )
00275     {
00276         val_array[0][i] = 0.0;
00277         val_array[val_array.LastY()][i] = 0.0;
00278     }// i
00279 
00280     for ( int j=1 ; j<mv_array.LengthY()-1 ; ++j )
00281     {
00282         val_array[j][0] = 0.0;
00283         val_array[j][val_array.LastX()] = 0.0;
00284         for ( int i=1 ; i<mv_array.LengthX()-1 ; ++i )
00285         {
00286             val_array[j][i] =0.0;
00287             for (int q=-1 ; q<=1 ; ++q)
00288                 for (int p=-1 ; p<=1 ; ++p)
00289                     val_array[j][i] = std::max( val_array[j][i] , (double)Norm1( mv_array[j+q][i+p] - mv_array[j][i] ) );
00290 
00291             total_cost += val_array[j][i];
00292 
00293         }// i
00294     }// j
00295 
00296 
00297     mean_cost = total_cost / 
00298                    static_cast<long double>( mv_array.LengthX()*mv_array.LengthY() );
00299 
00300     // next , Standard Deviation
00301     sd_cost = 0.0;
00302     
00303     for ( int j=1 ; j<mv_array.LengthY()-1 ; ++j )
00304     {
00305         for ( int i=1 ; i<mv_array.LengthX()-1 ; ++i )
00306         {
00307             diff = val_array[j][i] - mean_cost;
00308             diff *= diff;
00309 
00310             sd_cost += diff;
00311 
00312         }// i
00313     }// j
00314 
00315     // Get the variance ...
00316     sd_cost /= static_cast<long double>( mv_array.LengthX()*mv_array.LengthY() );
00317 
00318     // ... and then the SD
00319     sd_cost = std::sqrt( sd_cost );
00320 
00321     threshold = static_cast<float>( mean_cost + 1.5*sd_cost );
00322 
00323     // now go through and mark those that go above the threshold
00324     for ( int j=0 ; j<mv_array.LengthY() ; ++j )
00325         for ( int i=0 ; i<mv_array.LengthX() ; ++i )
00326 //            trans_map[j][i] = ( val_array[j][i] >= threshold )? true : false;
00327 trans_map[j][i] = false;
00328 
00329 //     bool contains_trans;
00330 
00331 //     for ( int j=0 ; j<mv_array.LengthY()/4 ; ++j )
00332 //     {
00333 //         for ( int i=0 ; i<mv_array.LengthX()/4 ; ++i )
00334 //         {     
00335 //             contains_trans = false;
00336 //             for ( int q=4*j ; q<4*(j+1) ; ++q )
00337 //             {
00338 //                 for ( int p=4*i ; p<4*(i+1) ; ++p )
00339 //                 {
00340 //                     if (trans_map[q][p])
00341 //                         contains_trans = true;
00342 //                 }// p
00343 //             }// q
00344 //             for ( int q=4*j ; q<4*(j+1) ; ++q )
00345 //                 for ( int p=4*i ; p<4*(i+1) ; ++p )
00346 //                     trans_map[q][p] = contains_trans;
00347 
00348 //         }// i
00349 //     }// j
00350 
00351      
00352 }
00353 
00354 
00355 MEData::~MEData()
00356 {
00357     // Delete the arrays of prediction costs
00358      for ( int i=m_pred_costs.First() ; i<=m_pred_costs.Last() ; ++i )
00359          delete m_pred_costs[i];
00360 
00361      for ( int i=m_inliers.First() ; i<=m_inliers.Last() ; ++i )
00362         delete m_inliers[i];
00363 }
00364 
00365 namespace dirac
00366 {
00368 
00371 ostream & operator<< (ostream & stream, MvCostData & cost)
00372 {
00373     stream << cost.SAD << " " << cost.mvcost;
00374 
00375     return stream;
00376 }
00377 
00379 
00382 istream & operator>> (istream & stream, MvCostData & cost)
00383 {
00384     stream >> cost.SAD >> cost.mvcost;
00385 
00386     return stream;
00387 }
00388 
00390 
00394 istream & operator>> (istream & stream, PredMode & mode)
00395 {
00396     int temp;
00397     stream >> temp;
00398     mode = (PredMode)temp;
00399 
00400     return stream;
00401 }
00402 
00403 // Overriden extractor operator for reading MvData data members
00404 istream &operator>> (istream & stream, MEData & me_data)
00405 {
00406     stream.ignore(1000, '\n');
00407     
00408     // input reference-independent information
00409     stream >> me_data.MBSplit();
00410     stream >> me_data.MBCommonMode();
00411     stream >> me_data.MBCosts();
00412     stream >> me_data.Mode();
00413     stream >> me_data.IntraCosts();
00414 
00415     if (me_data.m_pred_costs.Length() > 1)
00416         stream >> me_data.BiPredCosts();
00417 
00418     if (me_data.DC().Length() == 1)
00419     {
00420         stream >> me_data.DC( Y_COMP );
00421     }
00422     else if (me_data.DC().Length() == 3)
00423     {
00424         stream >> me_data.DC( Y_COMP );
00425         stream >> me_data.DC( U_COMP );
00426         stream >> me_data.DC( V_COMP );
00427     }
00428 
00429     // input reference information
00430     for (int i=1; i<=me_data.m_pred_costs.Length(); ++i)
00431     {
00432         stream >> me_data.Vectors(i);
00433         stream >> me_data.PredCosts(i);
00434         //stream >> me_data.GlobalMotionParameters(i);
00435         //stream >> me_data.GlobalMotionVectors(i);
00436         //stream >> me_data.GlobalMotionInliers(i);
00437     }
00438 
00439     return stream;
00440 }
00441 
00442 // Overriden operator for output of MvData member data (to file)
00443 ostream &operator<< (ostream & stream, MEData & me_data)
00444 {
00445     // output reference-independent information
00446     stream << endl << endl << me_data.MBSplit();
00447     stream << endl << me_data.MBCommonMode();
00448     stream << endl << me_data.MBCosts();
00449     stream << endl << me_data.Mode();
00450     stream << endl << me_data.IntraCosts() << endl;
00451 
00452     if (me_data.m_pred_costs.Length() > 1)
00453         stream << me_data.BiPredCosts();
00454 
00455     // output component DC values
00456     if (me_data.DC().Length() == 1)
00457     {
00458         stream << endl << me_data.DC( Y_COMP );
00459     }
00460     else if (me_data.DC().Length() == 3)
00461     {
00462         stream << endl << me_data.DC( Y_COMP );
00463         stream << endl << me_data.DC( U_COMP );
00464         stream << endl << me_data.DC( V_COMP );
00465     }
00466 
00467     // output reference information
00468     for (int i=1; i<=me_data.m_pred_costs.Length(); ++i)
00469     {
00470         stream << endl << me_data.Vectors(i);
00471         stream << endl << me_data.PredCosts(i) << endl;
00472         //stream << endl << me_data.GlobalMotionParameters(i) << endl;
00473         //stream << endl << me_data.GlobalMotionVectors(i) << endl;
00474         //stream << endl << me_data.GlobalMotionInliers(i) << endl;
00475     }
00476     
00477     return stream;
00478 }
00479 
00480 } // namespace dirac

Generated on Tue Dec 13 14:47:14 2005 for guliverkli by  doxygen 1.4.5