block_match.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:15k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. *
  3. * $Id: block_match.cpp,v 1.3 2005/01/30 05:11:42 gabest Exp $ $Name:  $
  4. *
  5. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  6. *
  7. * The contents of this file are subject to the Mozilla Public License
  8. * Version 1.1 (the "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. * http://www.mozilla.org/MPL/
  11. *
  12. * Software distributed under the License is distributed on an "AS IS" basis,
  13. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  14. * the specific language governing rights and limitations under the License.
  15. *
  16. * The Original Code is BBC Research and Development code.
  17. *
  18. * The Initial Developer of the Original Code is the British Broadcasting
  19. * Corporation.
  20. * Portions created by the Initial Developer are Copyright (C) 2004.
  21. * All Rights Reserved.
  22. *
  23. * Contributor(s): Thomas Davies (Original Author)
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
  27. * Public License Version 2.1 (the "LGPL"), in which case the provisions of
  28. * the GPL or the LGPL are applicable instead of those above. If you wish to
  29. * allow use of your version of this file only under the terms of the either
  30. * the GPL or LGPL and not to allow others to use your version of this file
  31. * under the MPL, indicate your decision by deleting the provisions above
  32. * and replace them with the notice and other provisions required by the GPL
  33. * or LGPL. If you do not delete the provisions above, a recipient may use
  34. * your version of this file under the terms of any one of the MPL, the GPL
  35. * or the LGPL.
  36. * ***** END LICENSE BLOCK ***** */
  37. #include <libdirac_motionest/block_match.h>
  38. #include <libdirac_motionest/me_utils.h>
  39. using namespace dirac;
  40. #include <cmath>
  41. using std::vector;
  42. namespace dirac
  43. {
  44. ValueType GetVar( const MVector& predmv , const MVector& mv )
  45. {
  46.     MVector diff;
  47.     diff.x = mv.x-predmv.x;
  48.     diff.y = mv.y-predmv.y;    
  49.     return std::max( Norm1( diff ) , 48 );
  50. }
  51. ValueType GetVar( const std::vector<MVector>& pred_list , const MVector& mv)
  52. {
  53.     ValueType sum=0;
  54.     MVector diff;
  55.     for (size_t i=0 ; i<pred_list.size() ; ++i)
  56.     {
  57.         diff.x = mv.x - pred_list[i].x;
  58.         diff.y = mv.y - pred_list[i].y;
  59.         sum += Norm1( diff );
  60.     }
  61.     return sum;
  62. }
  63. void AddNewVlist( CandidateList& vect_list, const MVector& mv, const int xr , const int yr , const int step )
  64. {
  65.       //Creates a new motion vector list in a square region around mv
  66.     vector<MVector> tmp_list;
  67.     vect_list.push_back(tmp_list);
  68.     int list_num=vect_list.size()-1;    
  69.     MVector tmp_mv( mv );
  70.     AddVect(vect_list , tmp_mv , list_num );
  71.     for ( int i=1 ; i<=xr ; ++i )
  72.     {
  73.         tmp_mv.x = mv.x + i*step;
  74.         AddVect( vect_list , tmp_mv , list_num );
  75.         tmp_mv.x = mv.x - i*step;        
  76.         AddVect( vect_list , tmp_mv , list_num );    
  77.     }
  78.     for ( int j=1 ; j<=yr ; ++j)
  79.     {
  80.         for ( int i=-xr ; i<=xr ; ++i)
  81.         {
  82.             tmp_mv.x = mv.x + i*step;
  83.             tmp_mv.y = mv.y + j*step;
  84.             AddVect(vect_list,tmp_mv,list_num);
  85.             tmp_mv.y = mv.y -j*step;
  86.             AddVect(vect_list,tmp_mv,list_num);            
  87.         }// i        
  88.     }// j
  89.     // If we've not managed to add any element to the list
  90.     // remove the list so we don't ever have to check its size
  91.     if ( vect_list[list_num].size() == 0 )
  92.         vect_list.erase( vect_list.begin() + list_num );
  93. }
  94. void AddNewVlist( CandidateList& vect_list , const MVector& mv , const int xr , const int yr)
  95. {
  96.       // Creates a new motion vector list in a square region around mv
  97.     
  98.     vector<MVector> tmp_list;
  99.     vect_list.push_back(tmp_list);
  100.     int list_num=vect_list.size()-1;    
  101.     MVector tmp_mv(mv);
  102.     AddVect(vect_list,tmp_mv,list_num);
  103.     for ( int i=1 ; i<=xr ; ++i)
  104.     {
  105.         tmp_mv.x = mv.x + i;
  106.         AddVect( vect_list , tmp_mv , list_num );
  107.         tmp_mv.x = mv.x - i;        
  108.         AddVect( vect_list , tmp_mv , list_num );    
  109.     }
  110.     for ( int j=1 ; j<=yr ; ++j)
  111.     {
  112.         for ( int i=-xr ; i<=xr ; ++i)
  113.         {
  114.             tmp_mv.x = mv.x + i;
  115.             tmp_mv.y = mv.y + j;
  116.             AddVect( vect_list , tmp_mv , list_num );
  117.             tmp_mv.y = mv.y-j;
  118.             AddVect( vect_list , tmp_mv , list_num );            
  119.         }        
  120.     }
  121.     // If we've not managed to add any element to the list
  122.     // remove the list so we don't ever have to check its size
  123.     if ( vect_list[list_num].size() == 0 )                 
  124.         vect_list.erase( vect_list.begin() + list_num );
  125. }
  126. void AddNewVlistD( CandidateList& vect_list , const MVector& mv , const int xr , const int yr )
  127. {
  128.       //As above, but using a diamond pattern
  129.     vector<MVector> tmp_list;
  130.     vect_list.push_back( tmp_list );
  131.     int list_num=vect_list.size()-1;    
  132.     int xlim;
  133.     MVector tmp_mv( mv );
  134.     AddVect( vect_list , tmp_mv , list_num );
  135.     for ( int i=1 ; i<=xr ; ++i)
  136.     {
  137.         tmp_mv.x = mv.x + i;
  138.         AddVect( vect_list , tmp_mv , list_num );
  139.         tmp_mv.x = mv.x - i;        
  140.         AddVect( vect_list , tmp_mv , list_num );    
  141.     }
  142.     for ( int j=1 ; j<=yr ; ++j)
  143.     {
  144.         xlim = xr * (yr-std::abs(j)) / yr;        
  145.         for ( int i=-xlim ; i<=xlim ; ++i)
  146.         {
  147.             tmp_mv.x = mv.x + i;
  148.             tmp_mv.y = mv.y + j;
  149.             AddVect( vect_list , tmp_mv , list_num );
  150.             tmp_mv.y = mv.y - j;
  151.             AddVect( vect_list , tmp_mv , list_num );            
  152.         }        
  153.     }
  154.     // If we've not managed to add any element to the list
  155.     // remove the list so we don't ever have to check its size
  156.     if ( vect_list[list_num].size() == 0 )                
  157.         vect_list.erase( vect_list.begin() + list_num );
  158. }
  159. void AddVect(CandidateList& vect_list,const MVector& mv,int list_num)
  160. {
  161.     bool is_in_list=false;
  162.     
  163.     size_t lnum=0;
  164.     size_t i;    
  165.     while( !is_in_list && lnum<vect_list.size() )
  166.     {
  167.         i=0;        
  168.         while( !is_in_list && i<vect_list[lnum].size())
  169.         {        
  170.             if ( vect_list[lnum][i].x == mv.x && vect_list[lnum][i].y == mv.y )    
  171.                 is_in_list=true;        
  172.             ++i;    
  173.         }
  174.         ++lnum;
  175.     }
  176.     if ( !is_in_list )
  177.         vect_list[list_num].push_back(mv);
  178.     
  179. }
  180. BlockMatcher::BlockMatcher( const PicArray& pic_data , const PicArray& ref_data , const OLBParams& bparams ,
  181.                             const MvArray& mv_array , const TwoDArray< MvCostData >& cost_array):
  182.     m_pic_data(pic_data), 
  183.     m_ref_data(ref_data),
  184.     m_mv_array(mv_array),
  185.     m_cost_array(cost_array),
  186.     m_simplediff( ref_data , pic_data ), //NB: ORDER!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  187.     m_checkdiff( ref_data , pic_data ),
  188.     m_simplediffup( ref_data , pic_data ),
  189.     m_checkdiffup( ref_data , pic_data ),
  190.     m_bparams(bparams)
  191. {}
  192.     
  193. void BlockMatcher::FindBestMatch(int xpos , int ypos ,
  194.                                  const CandidateList& cand_list,
  195.                                  const MVector& mv_prediction,
  196.                                  float lambda)
  197. {
  198.     BlockDiffParams dparams;
  199.     dparams.SetBlockLimits( m_bparams , m_pic_data , xpos , ypos);
  200.     lambda /= m_bparams.Xblen()*m_bparams.Yblen();
  201.     lambda *= dparams.Xl()*dparams.Yl();
  202.     
  203.     // Pointer to either a simple block diff object, or a bounds-checking one
  204.     BlockDiff* mydiff;
  205.        //now test against the offsets in the MV list to get the lowest cost//
  206.       //////////////////////////////////////////////////////////////////////    
  207.     // Numbers of the lists to do more searching in
  208.     vector<int> list_nums; 
  209.     // Costs of the initial vectors in each list
  210.     OneDArray<float> list_costs( cand_list.size() );
  211.     // The minimum cost so far
  212.     float min_cost;    
  213.     // First test the first in each of the lists to choose which lists to pursue
  214.     MvCostData best_costs;
  215.     // Initialise so that we choose a valid vector to start with!
  216.     best_costs.total=100000000.0f;
  217.     MVector best_mv( cand_list[0][0] );
  218.     MVector cand_mv;
  219.     MvCostData cand_costs;
  220.     for (size_t lnum=0 ; lnum<cand_list.size() ; ++lnum )
  221.     {
  222.         cand_mv = cand_list[lnum][0];
  223.         cand_costs.mvcost = GetVar( mv_prediction , cand_mv );
  224.         // See whether we need to do bounds checking or not
  225.         if (( dparams.Xp()+cand_mv.x )<0 || ( dparams.Xp()+dparams.Xl()+cand_mv.x) >= m_ref_data.LengthX() ||
  226.             (dparams.Yp()+cand_mv.y)<0 || (dparams.Yp()+dparams.Yl()+cand_mv.y) >= m_ref_data.LengthY() )
  227.             mydiff = &m_checkdiff;
  228.         else
  229.             mydiff = &m_simplediff;    
  230.         cand_costs.SAD = mydiff->Diff( dparams , cand_mv );
  231.         cand_costs.SetTotal( lambda );
  232.         if ( cand_costs.total < best_costs.total)
  233.         {
  234.             best_costs = cand_costs;
  235.             best_mv = cand_mv ;
  236.         }
  237.         list_costs[lnum] = cand_costs.total;
  238.     }// lnum
  239.     // Select which lists we're going to use //
  240.     ///////////////////////////////////////////
  241.     min_cost = list_costs[0];
  242.     for ( int lnum=1 ; lnum<list_costs.Length() ; ++lnum)
  243.     {
  244.         if ( list_costs[lnum]<min_cost )
  245.             min_cost = list_costs[lnum];
  246.     }// lnum
  247.     for ( int lnum=0 ; lnum<list_costs.Length() ; ++lnum)
  248.     {
  249.         // Only do lists whose 1st element isn't too far off best
  250.         if ( list_costs[lnum] < 1.5*min_cost ) // (value of 1.5 TBD) 
  251.             list_nums.push_back( lnum );
  252.     }// lnum
  253.     // Ok, now we know which lists to pursue. Just go through all of them //
  254.     ////////////////////////////////////////////////////////////////////////
  255.     int list_num;
  256.     for ( size_t num=0 ; num<list_nums.size() ; ++num)
  257.     {
  258.         list_num = list_nums[num];
  259.         for (size_t i=1 ; i<cand_list[list_num].size() ; ++i)
  260.         {//start at 1 since did 0 above
  261.             cand_mv = cand_list[list_num][i];
  262.             cand_costs.mvcost =  GetVar( mv_prediction , cand_mv);
  263.             
  264.             if ((dparams.Xp()+cand_mv.x)<0 || (dparams.Xp()+dparams.Xl()+cand_mv.x) > m_ref_data.LengthX() ||
  265.                 (dparams.Yp()+cand_mv.y)<0 || (dparams.Yp()+dparams.Yl()+cand_mv.y) > m_ref_data.LengthY() )
  266.                 mydiff = &m_checkdiff;
  267.             else
  268.                 mydiff = &m_simplediff;
  269.             cand_costs.SAD = mydiff->Diff( dparams , cand_mv );
  270.             cand_costs.SetTotal( lambda );
  271.             
  272.             if ( cand_costs.total < best_costs.total)
  273.             {
  274.                 best_costs = cand_costs;
  275.                 best_mv = cand_mv;
  276.             }
  277.         }// i
  278.     }// num
  279.     // Write the results in the arrays //
  280.     /////////////////////////////////////
  281.     m_mv_array[ypos][xpos] = best_mv;
  282.     m_cost_array[ypos][xpos] = best_costs;
  283. }
  284. void BlockMatcher::FindBestMatchSubp(int xpos, int ypos,
  285.                                       const CandidateList& cand_list,
  286.                                       const MVector& mv_prediction,
  287.                                       float lambda)
  288. {
  289.     BlockDiffParams dparams;
  290.     dparams.SetBlockLimits( m_bparams , m_pic_data , xpos , ypos);    
  291.     // Pointer to either a simple block diff object, or a bounds-checking one
  292.     BlockDiff* mydiff;
  293.        //now test against the offsets in the MV list to get the lowest cost//
  294.       //////////////////////////////////////////////////////////////////////    
  295.     // Numbers of the lists to do more searching in
  296.     vector<int> list_nums; 
  297.     // Costs of the initial vectors in each list
  298.     OneDArray<float> list_costs( cand_list.size() );
  299.     // The minimum cost so far
  300.     float min_cost;    
  301.     // First test the first in each of the lists to choose which lists to pursue
  302.     MvCostData best_costs( m_cost_array[ypos][xpos] );
  303.     MVector best_mv( m_mv_array[ypos][xpos] );
  304.     MvCostData cand_costs;
  305.     MVector cand_mv;
  306.     for (size_t list_num=0 ; list_num<cand_list.size() ; ++list_num )
  307.     {
  308.         cand_mv = cand_list[list_num][0];
  309.         cand_costs.mvcost = GetVar( mv_prediction , cand_mv );
  310.         // See whether we need to do bounds checking or not
  311.         if (   (( dparams.Xp()<<1 )+(cand_mv.x>>2))<0 
  312.             || ((( dparams.Xp()+dparams.Xl() )<<1)+(cand_mv.x>>2)) >= m_ref_data.LengthX()
  313.             || (( dparams.Yp()<<1)+(cand_mv.y>>2))<0 
  314.             || (((dparams.Yp()+dparams.Yl())<<1)+(cand_mv.y>>2)) >= m_ref_data.LengthY() )
  315.             mydiff = &m_checkdiffup;
  316.         else
  317.             mydiff = &m_simplediffup;    
  318.         cand_costs.SAD = mydiff->Diff( dparams , cand_mv );
  319.         cand_costs.SetTotal( lambda );
  320.  
  321.        if (cand_costs.total< best_costs.total)
  322.         {
  323.             best_costs = cand_costs;
  324.             best_mv = cand_mv;
  325.         }
  326.         
  327.         list_costs[list_num] = cand_costs.total;
  328.     }// list_num
  329.     // Select which lists we're going to use //
  330.     ///////////////////////////////////////////
  331.     min_cost = list_costs[0];
  332.     for ( int lnum=1 ; lnum<list_costs.Length() ; ++lnum)
  333.     {
  334.         if ( list_costs[lnum]<min_cost )
  335.             min_cost = list_costs[lnum];
  336.     }// lnum
  337.     for ( int lnum=0 ; lnum<list_costs.Length() ; ++lnum )
  338.     {
  339.         // Only do lists whose 1st element isn't too far off best
  340.         if ( list_costs[lnum] < 1.5*min_cost ) // (value of 1.5 TBD) 
  341.             list_nums.push_back( lnum );
  342.     }// lnum
  343.     // Ok, now we know which lists to pursue. Just go through all of them //
  344.     ////////////////////////////////////////////////////////////////////////
  345.     int list_num;
  346.     for ( size_t num=0 ; num<list_nums.size() ; ++num)
  347.     {
  348.         list_num = list_nums[num];
  349.         for (size_t i=1 ; i<cand_list[list_num].size() ; ++i)
  350.         {//start at 1 since did 0 above
  351.             cand_mv = cand_list[list_num][i];
  352.             cand_costs.mvcost = GetVar( mv_prediction , cand_mv );
  353.             if (   (( dparams.Xp()<<1 )+( cand_mv.x>>2 ))<0 
  354.                 || ((( dparams.Xp()+dparams.Xl() )<<1)+( cand_mv.x>>2 )) >= m_ref_data.LengthX()
  355.                 || (( dparams.Yp()<<1 )+( cand_mv.y>>2 ))<0 
  356.                 || ((( dparams.Yp()+dparams.Yl() )<<1)+(cand_mv.y>>2)) >= m_ref_data.LengthY() )
  357.                  mydiff = &m_checkdiffup;
  358.             else
  359.                 mydiff = &m_simplediffup;
  360.             cand_costs.SAD = mydiff->Diff( dparams , cand_mv );
  361.             cand_costs.SetTotal( lambda );
  362.             if (cand_costs.total< best_costs.total)
  363.             {
  364.                 best_costs = cand_costs;
  365.                 best_mv = cand_mv;
  366.             }
  367.         }// i
  368.     }// num
  369.     // Write the results in the arrays //
  370.     /////////////////////////////////////
  371.      m_mv_array[ypos][xpos] = best_mv;
  372.      m_cost_array[ypos][xpos] = best_costs;   
  373. }
  374. } // namespace dirac