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 ([email protected])
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 }

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