- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# me_utils.cpp

    00001 /* ***** BEGIN LICENSE BLOCK *****
    00002 *
    00003 * $Id: me_utils.cpp,v 1.2 2005/01/30 05:11:42 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), Peter Meerwald (pmeerw@users.sourceforge.net)
    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
    00039 //-------------------------------//
    00040 //utilities for motion estimation//
    00041 //-------------------------------//
    00043
    00044 #include <libdirac_motionest/me_utils.h>
    00045 #include <libdirac_common/common.h>
    00046 using namespace dirac;
    00047
    00048 #include <algorithm>
    00049
    00050 void BlockDiffParams::SetBlockLimits( const OLBParams& bparams ,
    00051                                       const PicArray& pic_data ,
    00052                                       const int xbpos , const int ybpos)
    00053 {
    00054     const int loc_xp = xbpos * bparams.Xbsep() - bparams.Xoffset();
    00055     const int loc_yp = ybpos * bparams.Ybsep() - bparams.Yoffset();
    00056
    00057     m_xp=std::max( loc_xp , 0 );
    00058     m_yp=std::max( loc_yp , 0 );
    00059
    00060     m_xl = bparams.Xblen() - m_xp + loc_xp;
    00061     m_yl = bparams.Yblen() - m_yp + loc_yp;
    00062
    00063      //constrain block lengths to fall within the picture
    00064     m_xl = ( ( m_xp + m_xl - 1) > pic_data.LastX() ) ? ( pic_data.LastX() + 1 - m_xp ): m_xl;
    00065     m_yl = ( ( m_yp + m_yl - 1) > pic_data.LastY() ) ? ( pic_data.LastY() + 1 - m_yp ) : m_yl;
    00066
    00067 }
    00068
    00069 // Block difference class functions
    00070
    00071 // Constructors ...
    00072
    00073 BlockDiff::BlockDiff(const PicArray& ref,const PicArray& pic) :
    00074     pic_data( pic ),
    00075     ref_data( ref )
    00076 {}
    00077
    00078 SimpleBlockDiff::SimpleBlockDiff( const PicArray& ref , const PicArray& pic ) :
    00079     BlockDiff( ref , pic )
    00080 {}
    00081
    00082 BChkBlockDiff::BChkBlockDiff( const PicArray& ref , const PicArray& pic ) :
    00083     BlockDiff( ref , pic )
    00084 {}
    00085
    00086 IntraBlockDiff::IntraBlockDiff( const PicArray& pic ) :
    00087     pic_data( pic )
    00088 {}
    00089
    00090 BiBlockDiff::BiBlockDiff( const PicArray& ref1 , const PicArray& ref2 ,
    00091                           const PicArray& pic) :
    00092     pic_data( pic ),
    00093     ref_data1( ref1 ),
    00094     ref_data2( ref2 )
    00095 {}
    00096
    00097 BiSimpleBlockDiff::BiSimpleBlockDiff( const PicArray& ref1 , const PicArray& ref2 ,
    00098                                       const PicArray& pic) :
    00099     BiBlockDiff(ref1 , ref2 , pic)
    00100 {}
    00101
    00102 BiBChkBlockDiff::BiBChkBlockDiff( const PicArray& ref1 , const PicArray& ref2 ,
    00103                                   const PicArray& pic ) :
    00104     BiBlockDiff(ref1 , ref2 , pic)
    00105 {}
    00106
    00107 BlockDiffUp::BlockDiffUp( const PicArray& ref , const PicArray& pic):
    00108     BlockDiff( ref , pic )
    00109 {}
    00110
    00111 SimpleBlockDiffUp::SimpleBlockDiffUp( const PicArray& ref , const PicArray& pic ) :
    00112     BlockDiffUp( ref , pic )
    00113 {}
    00114
    00115 BChkBlockDiffUp::BChkBlockDiffUp(const PicArray& ref,const PicArray& pic) :
    00116     BlockDiffUp( ref , pic )
    00117 {}
    00118
    00119 BiBlockDiffUp::BiBlockDiffUp( const PicArray& ref1 , const PicArray& ref2 ,
    00120                               const PicArray& pic) :
    00121     BiBlockDiff( ref1 , ref2 , pic )
    00122 {}
    00123
    00124 BiSimpleBlockDiffUp::BiSimpleBlockDiffUp( const PicArray& ref1 , const PicArray& ref2 ,
    00125                                           const PicArray& pic ):
    00126     BiBlockDiffUp( ref1 , ref2 , pic)
    00127 {}
    00128
    00129 BiBChkBlockDiffUp::BiBChkBlockDiffUp( const PicArray& ref1 , const PicArray& ref2 ,
    00130                                       const PicArray& pic ) :
    00131     BiBlockDiffUp( ref1 , ref2 , pic)
    00132 {}
    00133
    00134 // Difference functions ...
    00135
    00136 float SimpleBlockDiff::Diff( const BlockDiffParams& dparams, const MVector& mv )
    00137 {
    00138
    00139     ValueType diff;
    00140
    00141     CalcValueType sum( 0 );
    00142
    00143     for (int j=dparams.Yp() ; j != dparams.Yp()+dparams.Yl() ; ++j )
    00144     {
    00145         for(int i=dparams.Xp() ; i!= dparams.Xp()+dparams.Xl() ; ++i )
    00146         {
    00147             diff = pic_data[j][i]-ref_data[j+mv.y][i+mv.x];
    00148             sum += std::abs( diff );
    00149         }// i, k
    00150     }// j, l
    00151
    00152     return static_cast<float>( sum );
    00153 }
    00154
    00155 float BChkBlockDiff::Diff( const BlockDiffParams& dparams, const MVector& mv )
    00156 {
    00157
    00158     const int xmax = ref_data.LengthX();
    00159     const int ymax = ref_data.LengthY();
    00160
    00161     ValueType diff;
    00162
    00163     CalcValueType sum( 0 );
    00164
    00165     for ( int j=dparams.Yp() ; j!=dparams.Yp()+dparams.Yl() ; ++j )
    00166     {
    00167         for( int i=dparams.Xp() ; i!=dparams.Xp()+dparams.Xl() ; ++i )
    00168         {
    00169             diff = pic_data[j][i] - ref_data[BChk(j+mv.y , ymax)][BChk(i+mv.x , xmax)];
    00170             sum += std::abs( diff );
    00171
    00172         }// i
    00173     }// j
    00174
    00175     return static_cast<float>( sum );
    00176 }
    00177
    00178 float IntraBlockDiff::Diff( const BlockDiffParams& dparams , ValueType& dc_val )
    00179 {
    00180
    00181      //computes the cost if block is predicted by its dc component
    00182
    00183     CalcValueType int_dc( 0 );
    00184
    00185     for ( int j=dparams.Yp() ; j!=dparams.Yp()+dparams.Yl() ; ++j)
    00186         for(int i=dparams.Xp(); i!=dparams.Xp()+dparams.Xl() ; ++i )
    00187             int_dc += static_cast<int>( pic_data[j][i] );
    00188
    00189     int_dc /= ( dparams.Xl() * dparams.Yl() );
    00190
    00191     // Just give dc to 8-bit accuracy
    00192     dc_val = static_cast<ValueType>( (int_dc+2)>>2 );
    00193
    00194     // Now compute the resulting SAD
    00195     ValueType dc( dc_val<<2 );
    00196     CalcValueType intra_cost( 0 );
    00197
    00198     for (int j=dparams.Yp(); j!=dparams.Yp()+dparams.Yl() ; ++j)
    00199         for( int i=dparams.Xp() ; i!=dparams.Xp()+dparams.Xl() ;++i )
    00200             intra_cost += std::abs( pic_data[j][i] - dc );
    00201
    00202     return static_cast<float>( intra_cost );
    00203 }
    00204
    00205 float BiSimpleBlockDiff::Diff( const BlockDiffParams& dparams, const MVector& mv1,const MVector& mv2){
    00206
    00207     CalcValueType sum( 0 );
    00208
    00209     ValueType diff;
    00210
    00211     for ( int j=dparams.Yp(); j!=dparams.Yp()+dparams.Yl(); ++j )
    00212     {
    00213         for( int i=dparams.Xp() ; i!=dparams.Xp()+dparams.Xl() ; ++i )
    00214         {
    00215             diff = pic_data[j][i]-( ( ref_data1[j+mv1.y][i+mv1.x] + 1 )>>1 );
    00216             diff -= ( ( ref_data2[j+mv2.y][i+mv2.x] + 1 )>>1 );
    00217
    00218             sum += std::abs( diff );
    00219         }// i
    00220     }// j
    00221
    00222     return static_cast<float>( sum );
    00223 }
    00224
    00225 float BiBChkBlockDiff::Diff( const BlockDiffParams& dparams, const MVector& mv1,const MVector& mv2){
    00226
    00227     ValueType diff;
    00228     const int xmax1 = ref_data1.LengthX();
    00229     const int ymax1 = ref_data1.LengthY();
    00230
    00231     const int xmax2 = ref_data2.LengthX();
    00232     const int ymax2 = ref_data2.LengthY();
    00233
    00234     CalcValueType sum( 0 );
    00235
    00236     for ( int j=dparams.Yp() ; j!=dparams.Yp() + dparams.Yl() ; ++j )
    00237     {
    00238         for( int i=dparams.Xp() ; i!=dparams.Xp() + dparams.Xl() ; ++i )
    00239         {
    00240             diff = pic_data[j][i]-( ( ref_data1[BChk(j+mv1.y , ymax1)][BChk(i+mv1.x , xmax1)] + 1 )>>1 );
    00241             diff -= ( ( ref_data2[BChk(j+mv2.y , ymax2)][BChk(i+mv2.x , xmax2)] + 1 )>>1 );
    00242
    00243             sum += std::abs( diff );
    00244         }// i
    00245     }// j
    00246
    00247     return static_cast<float>( sum );
    00248 }
    00249
    00250 float SimpleBlockDiffUp::Diff( const BlockDiffParams& dparams, const MVector& mv )
    00251 {
    00252
    00253     //Coordinates in the image being written to
    00254     const ImageCoords StartPos(dparams.Xp(),dparams.Yp());
    00255     const ImageCoords EndPos(StartPos.x+dparams.Xl(),StartPos.y+dparams.Yl());
    00256
    00257     //the rounded motion vectors, accurate to 1/2 pel
    00258     //NB: bitshift rounds negative numbers DOWN, as required
    00259     const MVector roundvec(mv.x>>2,mv.y>>2);
    00260
    00261     //remainder, giving 1/8 pel accuracy, needed for linear interp
    00262     const MVector rmdr(mv.x-(roundvec.x<<2),mv.y-(roundvec.y<<2));
    00263
    00264     //Set up the start point in the reference image.
    00265     const ImageCoords RefStart((StartPos.x<<1) + roundvec.x,(StartPos.y<<1) + roundvec.y);
    00266
    00267
    00268     //weights for doing linear interpolation, calculated from the remainder values
    00269
    00270     const ValueType TLweight((4-rmdr.x)*(4-rmdr.y));
    00271     const ValueType TRweight(rmdr.x*(4-rmdr.y));
    00272     const ValueType BLweight((4-rmdr.x)*rmdr.y);
    00273     const ValueType BRweight(rmdr.x*rmdr.y);
    00274
    00275     CalcValueType sum( 0 );
    00276
    00277     ValueType temp;
    00278
    00279     for(int c = StartPos.y, uY = RefStart.y; c < EndPos.y; ++c, uY += 2){
    00280         for(int l = StartPos.x, uX = RefStart.x; l < EndPos.x; ++l, uX += 2){
    00281             temp = (
    00282                     TLweight * ref_data[uY][uX] +
    00283                     TRweight * ref_data[uY][uX+1] +
    00284                     BLweight * ref_data[uY+1][uX] +
    00285                     BRweight * ref_data[uY+1][uX+1] +
    00286                     8
    00287                     )>>4;
    00288
    00289             sum += std::abs( pic_data[c][l] - temp );
    00290         }//l
    00291     }//c
    00292
    00293     return static_cast<float>( sum );
    00294 }
    00295
    00296 float BChkBlockDiffUp::Diff(  const BlockDiffParams& dparams, const MVector& mv )
    00297 {
    00298
    00299     //the picture sizes
    00300     const int DoubleXdim=ref_data.LengthX();
    00301     const int DoubleYdim=ref_data.LengthY();
    00302
    00303     //Coordinates in the image being written to
    00304     const ImageCoords StartPos(dparams.Xp(),dparams.Yp());
    00305     const ImageCoords EndPos(StartPos.x+dparams.Xl(),StartPos.y+dparams.Yl());
    00306
    00307     //the rounded motion vectors, accurate to 1/2 pel
    00308     //NB: bitshift rounds negative numbers DOWN, as required
    00309     const MVector roundvec(mv.x>>2,mv.y>>2);
    00310
    00311     //remainder, giving 1/8 pel accuracy, needed for linear interp
    00312     const MVector rmdr(mv.x-(roundvec.x<<2),mv.y-(roundvec.y<<2));
    00313
    00314     //Set up the start point in the reference image.
    00315     const ImageCoords RefStart((StartPos.x<<1) + roundvec.x,(StartPos.y<<1) + roundvec.y);
    00316
    00317
    00318     //weights for doing linear interpolation, calculated from the remainder values
    00319
    00320     const ValueType    TLweight((4-rmdr.x)*(4-rmdr.y));
    00321     const ValueType    TRweight(rmdr.x*(4-rmdr.y));
    00322     const ValueType    BLweight((4-rmdr.x)*rmdr.y);
    00323     const ValueType    BRweight(rmdr.x*rmdr.y);
    00324
    00325     CalcValueType sum( 0 );
    00326
    00327     ValueType temp;
    00328
    00329     for(int c = StartPos.y, uY = RefStart.y; c < EndPos.y; ++c, uY += 2)
    00330     {
    00331         for(int l = StartPos.x, uX = RefStart.x; l < EndPos.x; ++l, uX += 2)
    00332         {
    00333             temp = (
    00334                     TLweight * ref_data[BChk(uY,DoubleYdim)][BChk(uX,DoubleXdim)] +
    00335                     TRweight * ref_data[BChk(uY,DoubleYdim)][BChk(uX+1,DoubleXdim)] +
    00336                     BLweight * ref_data[BChk(uY+1,DoubleYdim)][BChk(uX,DoubleXdim)] +
    00337                     BRweight * ref_data[BChk(uY+1,DoubleYdim)][BChk(uX+1,DoubleXdim)] +
    00338                     8
    00339                     )>>4;
    00340
    00341             sum += ( std::abs( pic_data[c][l] - temp ) );
    00342         }//l
    00343     }//c
    00344
    00345     return static_cast<float>( sum );
    00346
    00347 }
    00348
    00349 float BiSimpleBlockDiffUp::Diff( const BlockDiffParams& dparams, const MVector& mv1, const MVector& mv2){
    00350
    00351     //the start and end points in the current frame
    00352     const ImageCoords StartPos(dparams.Xp(),dparams.Yp());//Coordinates in the current image
    00353     const ImageCoords EndPos(StartPos.x+dparams.Xl(),StartPos.y+dparams.Yl());
    00354
    00355     //the motion vectors rounded to 1/2 pel accuracy
    00356     const MVector roundvec1(mv1.x>>2,mv1.y>>2);
    00357     const MVector roundvec2(mv2.x>>2,mv2.y>>2);
    00358
    00359     //the remainders giving 1/8 pel accuracy
    00360     const MVector rmdr1(mv1.x-(roundvec1.x<<2),mv1.y-(roundvec1.y<<2));
    00361     const MVector rmdr2(mv2.x-(roundvec2.x<<2),mv2.y-(roundvec2.y<<2));
    00362
    00363     //the starting points of the reference blocks in the reference images, to 1/2 pel accuracy
    00364     const ImageCoords RefStart1((StartPos.x<<1) + roundvec1.x,(StartPos.y<<1) + roundvec1.y);
    00365     const ImageCoords RefStart2((StartPos.x<<1) + roundvec2.x,(StartPos.y<<1) + roundvec2.y);
    00366
    00367     //weights for doing linear interpolation, calculated from the remainder values
    00368     const ValueType    TLweight1((4-rmdr1.x)*(4-rmdr1.y));
    00369     const ValueType    TRweight1(rmdr1.x*(4-rmdr1.y));
    00370     const ValueType    BLweight1((4-rmdr1.x)*rmdr1.y);
    00371     const ValueType    BRweight1(rmdr1.x*rmdr1.y);
    00372
    00373     const ValueType    TLweight2((4-rmdr2.x)*(4-rmdr2.y));
    00374     const ValueType    TRweight2(rmdr2.x*(4-rmdr2.y));
    00375     const ValueType    BLweight2((4-rmdr2.x)*rmdr2.y);
    00376     const ValueType    BRweight2(rmdr2.x*rmdr2.y);
    00377
    00378     CalcValueType temp;
    00379
    00380     CalcValueType sum( 0 );
    00381
    00382     for(int c = StartPos.y, uY1 = RefStart1.y,uY2=RefStart2.y; c < EndPos.y; ++c, uY1 += 2,uY2 += 2){
    00383         for(int l = StartPos.x, uX1 = RefStart1.x,uX2=RefStart2.x; l < EndPos.x; ++l, uX1 += 2, uX2 += 2){
    00384             temp = (
    00385                     TLweight1 * ref_data1[uY1][uX1] +
    00386                     TRweight1 * ref_data1[uY1][uX1+1] +
    00387                     BLweight1 * ref_data1[uY1+1][uX1] +
    00388                     BRweight1 * ref_data1[uY1+1][uX1+1] +
    00389                     16
    00390                     )>>5;
    00391
    00392             temp += (
    00393                     TLweight2 * ref_data2[uY2][uX2] +
    00394                     TRweight2 * ref_data2[uY2][uX2+1] +
    00395                     BLweight2 * ref_data2[uY2+1][uX2] +
    00396                     BRweight2 * ref_data2[uY2+1][uX2+1] +
    00397                     16
    00398                     )>>5;
    00399
    00400             sum += std::abs( pic_data[c][l] - temp );
    00401         }//l
    00402     }//c
    00403
    00404     return static_cast<float>( sum );
    00405 }
    00406
    00407 float BiBChkBlockDiffUp::Diff( const BlockDiffParams& dparams, const MVector& mv1, const MVector& mv2)
    00408 {
    00409
    00410     //as above, but with bounds checking
    00411     const int xmax1 = ref_data1.LengthX();
    00412     const int ymax1 = ref_data1.LengthY();
    00413     const int xmax2 = ref_data2.LengthX();
    00414     const int ymax2 = ref_data2.LengthY();
    00415
    00416     //the start and end points in the current frame
    00417     const ImageCoords StartPos(dparams.Xp(),dparams.Yp());//Coordinates in the current image
    00418     const ImageCoords EndPos(StartPos.x+dparams.Xl(),StartPos.y+dparams.Yl());
    00419
    00420     //the motion vectors rounded to 1/2 pel accuracy
    00421     const MVector roundvec1(mv1.x>>2,mv1.y>>2);
    00422     const MVector roundvec2(mv2.x>>2,mv2.y>>2);
    00423
    00424     //the remainders giving 1/8 pel accuracy
    00425     const MVector rmdr1(mv1.x-(roundvec1.x<<2),mv1.y-(roundvec1.y<<2));
    00426     const MVector rmdr2(mv2.x-(roundvec2.x<<2),mv2.y-(roundvec2.y<<2));
    00427
    00428     //the starting points of the reference blocks in the reference images, to 1/2 pel accuracy
    00429     const ImageCoords RefStart1((StartPos.x<<1) + roundvec1.x,(StartPos.y<<1) + roundvec1.y);
    00430     const ImageCoords RefStart2((StartPos.x<<1) + roundvec2.x,(StartPos.y<<1) + roundvec2.y);
    00431
    00432     //weights for doing linear interpolation, calculated from the remainder values
    00433     const ValueType TLweight1((4-rmdr1.x)*(4-rmdr1.y));
    00434     const ValueType TRweight1(rmdr1.x*(4-rmdr1.y));
    00435     const ValueType BLweight1((4-rmdr1.x)*rmdr1.y);
    00436     const ValueType BRweight1(rmdr1.x*rmdr1.y);
    00437
    00438     const ValueType TLweight2((4-rmdr2.x)*(4-rmdr2.y));
    00439     const ValueType TRweight2(rmdr2.x*(4-rmdr2.y));
    00440     const ValueType BLweight2((4-rmdr2.x)*rmdr2.y);
    00441     const ValueType BRweight2(rmdr2.x*rmdr2.y);
    00442
    00443     CalcValueType temp;
    00444
    00445     CalcValueType sum( 0 );
    00446
    00447     for(int c = StartPos.y, uY1 = RefStart1.y,uY2=RefStart2.y; c < EndPos.y; ++c, uY1 += 2,uY2 += 2)
    00448     {
    00449         for(int l = StartPos.x, uX1 = RefStart1.x,uX2=RefStart2.x; l < EndPos.x; ++l, uX1 += 2, uX2 += 2)
    00450         {
    00451             temp = (
    00452                     TLweight1 * ref_data1[BChk(uY1,ymax1)][BChk(uX1,xmax1)] +
    00453                     TRweight1 * ref_data1[BChk(uY1,ymax1)][BChk(uX1+1,xmax1)] +
    00454                     BLweight1 * ref_data1[BChk(uY1+1,ymax1)][BChk(uX1,xmax1)] +
    00455                     BRweight1 * ref_data1[BChk(uY1+1,ymax1)][BChk(uX1+1,xmax1)] +
    00456                     16)>>5;
    00457
    00458             temp += (
    00459                     TLweight2 * ref_data2[BChk(uY2,ymax2)][BChk(uX2,xmax2)] +
    00460                     TRweight2 * ref_data2[BChk(uY2,ymax2)][BChk(uX2+1,xmax2)] +
    00461                     BLweight2 * ref_data2[BChk(uY2+1,ymax2)][BChk(uX2,xmax2)] +
    00462                     BRweight2 * ref_data2[BChk(uY2+1,ymax2)][BChk(uX2+1,xmax2)]+
    00463                     16)>>5;
    00464
    00465             sum += std::abs( pic_data[c][l] - temp );
    00466         }//l
    00467     }//c
    00468
    00469     return static_cast<float>( sum );
    00470 }