- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# 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