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

多媒体编程

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. *
  3. * $Id: motion.h,v 1.2 2005/01/30 05:11:40 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), Chris Bowley
  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_common/common.h>
  38. #include <algorithm>
  39. #ifndef _MOTION_H
  40. #define _MOTION_H
  41. namespace dirac
  42. {
  43.     ////////////////////////////////////////////////////////////////
  44.     //classes and functions for motion estimation and compensation//
  45.     ////////////////////////////////////////////////////////////////
  46.     //classes
  47.     //! Motion vector class - just a pair
  48.     template <class T>
  49.     class MotionVector
  50.     {
  51.     public:
  52.         //! Constructor 
  53.         MotionVector<T>(T a, T b) : x(a), y(b) {};
  54.         //! Default construct - sets components to 0
  55.         MotionVector<T>() : x(0), y(0) {};
  56.         //! Constructor 
  57.         MotionVector<T>(T a) : x(a), y(a) {};
  58.         //! Addition 
  59.         inline MotionVector<T> operator+(const MotionVector<T>& argument) const;
  60.         //! Subtraction 
  61.         inline MotionVector<T> operator-(const MotionVector<T>& argument) const;
  62.         //! Scalar multiplication
  63.         inline MotionVector<T> operator*(const float argument) const;
  64.         //! Scalar multiplication
  65.         inline MotionVector<T> operator*(const int argument) const;
  66.         //! Bitshift of each component
  67.         inline MotionVector<T> operator<<(const int argument) const;
  68.         //! Bitshift of each component
  69.         inline MotionVector<T> operator>>(const int argument) const;
  70.         //! x and y components 
  71.         T x,y;
  72.     };
  73.     template <class T>
  74.     inline MotionVector<T> MotionVector<T>::operator+(const MotionVector<T>& argument) const 
  75.     {
  76.         MotionVector<T> temp;
  77.         temp.x = x + argument.x;
  78.         temp.y = y + argument.y;
  79.         return temp;
  80.     }
  81.     template <class T>
  82.     inline MotionVector<T>  MotionVector<T>::operator-(const MotionVector<T>& argument) const 
  83.     {
  84.         MotionVector<T> temp;
  85.         temp.x = x-argument.x;
  86.         temp.y = y-argument.y;
  87.         return temp;
  88.     }
  89.     template <class T>
  90.     inline MotionVector<T>  MotionVector<T>::operator*(const float argument) const 
  91.     {
  92.         MotionVector<T> temp;
  93.         temp.x = x*argument;
  94.         temp.y = y*argument;
  95.         return temp;
  96.     }
  97.     template <class T>
  98.     inline MotionVector<T>  MotionVector<T>::operator*(const int argument) const 
  99.     {
  100.         MotionVector<T> temp;
  101.         temp.x = x*argument;
  102.         temp.y = y*argument;
  103.         return temp;
  104.     }
  105.     template <class T>
  106.     inline MotionVector<T>  MotionVector<T>::operator<<(const int argument) const 
  107.     {
  108.         MotionVector<T> temp;
  109.         temp.x = x<<argument;
  110.         temp.y = y<<argument;
  111.         return temp;
  112.     }
  113.     template <class T>
  114.     inline MotionVector<T>  MotionVector<T>::operator>>(const int argument) const 
  115.     {
  116.         MotionVector<T> temp;
  117.         temp.x = x>>argument;
  118.         temp.y = y>>argument;
  119.         return temp;
  120.     }
  121.     //! Overloaded operator<< for MotionVector class for output to stream
  122.     template <class T>
  123.     std::ostream & operator<< (std::ostream & stream, MotionVector<T> & mv)
  124.     {
  125.         stream << mv.x << " " << mv.y;
  126.         return stream;
  127.     }
  128.     //! Overloaded operator>> for MotionVector class for input from stream
  129.     template <class T>
  130.     std::istream & operator>> (std::istream & stream, MotionVector<T> & mv)
  131.     {
  132.         stream >> mv.x;
  133.         stream >> mv.y;
  134.         return stream;
  135.     }
  136.     //! MVector class is a vector of ints 
  137.     typedef MotionVector<int> MVector;
  138.     //! ImageCoords class is a vector of ints 
  139.     typedef MotionVector<int> ImageCoords;
  140.     //! MvArray is a two-D array of MVectors
  141.     typedef TwoDArray<MVector> MvArray;
  142.     //! An array of float-based motion vectors for doing global motion calcs
  143.     typedef TwoDArray< MotionVector<float> > MvFloatArray;
  144.     //! Class for recording costs derived in motion estimation
  145.     class MvCostData
  146.     {
  147.     public:
  148.         //! Constructor
  149.         MvCostData():
  150.         SAD(0.0),
  151.         mvcost(0.0),
  152.         total(0.0){}
  153.         void SetTotal( const float lambda ){total = SAD + lambda*mvcost;}
  154.         //! The Sum of Absolute Differences - easier to compute than Sum-Squared Differences
  155.         float SAD;
  156.         //! The (Lagrangian-weighted) motion vector cost - the difference of a motion vector from its neighbouring vectors
  157.         float mvcost;
  158.         //! Total=SAD+mvcost
  159.         float total;
  160.     };
  161.     //! Class for all the motion vector data
  162.     /*!
  163.          Motion vector data: the motion vectors themselves, the blocks 
  164.          and macroblock modes.
  165.     */
  166.     class MvData
  167.     {
  168.     public:
  169.         //! Constructor
  170.         /*! 
  171.             Constructor takes:
  172.             param  xnumMB  the number of MBs horizontally
  173.             param  ynumMB  the number of MBs vertically
  174.             param  xnumblocks  the number of blocks horizontally
  175.             param  ynumblocks  the number of blocks vertically
  176.             param  num_refs  the number of references being used for the frame
  177.         */
  178.         MvData( const int xnumMB, int ynumMB , 
  179.                 const int xnumblocks, int ynumblocks ,  const int num_refs = 2);
  180.         //! Constructor
  181.         /*! 
  182.             Constructor. Numbers of blocks derived from the number of MBs
  183.             param  xnumMB  the number of MBs horizontally
  184.             param  ynumMB  the number of MBs vertically
  185.             param  num_refs  the number of references being used for the frame
  186.         */
  187.         MvData( const int xnumMB, int ynumMB ,  const int num_refs = 2);
  188.         //! Destructor
  189.         ~MvData();
  190.         //! Get the MVs for a reference
  191.         MvArray& Vectors(const int ref_id){return *( m_vectors[ref_id] );}
  192.         //! Get the MVs for a reference
  193.         const MvArray& Vectors(const int ref_id) const {return *( m_vectors[ref_id] );}
  194.         //! Get the global MVs for a reference
  195.         MvArray& GlobalMotionVectors(const int ref_id){return *( m_gm_vectors[ref_id] );}
  196.         //! Get the global MVs for a reference
  197.         const MvArray& GlobalMotionVectors(const int ref_id) const {return *( m_gm_vectors[ref_id] );} 
  198.         //! Get the DC values for each component
  199.         TwoDArray<ValueType>& DC(CompSort cs){return *( m_dc[cs] );}
  200.         //! Get the DC values for each component
  201.         const TwoDArray<ValueType>& DC(CompSort cs) const {return *( m_dc[cs] );}
  202.         //! Get a reference to the vector holding component DC values
  203.         const OneDArray< TwoDArray<ValueType>* >& DC() const {return m_dc;}
  204.         //! Get the block prediction modes
  205.         TwoDArray<PredMode>& Mode(){return m_modes;}
  206.         //! Get the block prediction modes
  207.         const TwoDArray<PredMode>& Mode() const {return m_modes;}
  208.      
  209.         //! Get the MB split level
  210.         TwoDArray<int>& MBSplit(){return m_mb_split;}
  211.         //! Get the MB split level
  212.         const TwoDArray<int>& MBSplit() const{return m_mb_split;}
  213.         //! Get the MB common mode parameters
  214.         TwoDArray<bool>& MBCommonMode(){return m_mb_common;}
  215.         //! Get the MB common mode parameters
  216.         const TwoDArray<bool>& MBCommonMode() const{return m_mb_common;}
  217.         //! Get the global motion model parameters
  218.         OneDArray<float>& GlobalMotionParameters(const int ref_id) { return *( m_gm_params[ref_id] ); }
  219.         //! Get the global motion model parameters
  220.         const OneDArray<float>& GlobalMotionParameters(const int ref_id) const { return *( m_gm_params[ref_id] ); }
  221.     private:
  222.         // Initialises the arrays of data
  223.         void InitMvData();
  224.         // The motion vectors
  225.         OneDArray<MvArray*> m_vectors;
  226.         // The global motion vectors
  227.         OneDArray<MvArray*> m_gm_vectors;
  228.         // The block modes
  229.         TwoDArray<PredMode> m_modes;
  230.         // The DC values
  231.         OneDArray< TwoDArray<ValueType>* > m_dc;
  232.         // The MB split levels
  233.         TwoDArray<int> m_mb_split;
  234.         // The MB common mode indicators 
  235.         TwoDArray<bool> m_mb_common;
  236.         // Global motion model parameters
  237.         OneDArray< OneDArray<float>* > m_gm_params;
  238.     };
  239.     //! Class for all the motion estimation data
  240.     /*!
  241.          Motion estimation data: derived from MvData class, also
  242.          incorporates costs for blocks and macroblocks
  243.     */
  244.     class MEData: public MvData
  245.     {
  246.     public:
  247.         //! Constructor
  248.         /*! 
  249.             Constructor takes:
  250.             param  xnumMB  the number of MBs horizontally
  251.             param  ynumMB  the number of MBs vertically
  252.             param  xnumblocks  the number of blocks horizontally
  253.             param  ynumblocks  the number of blocks vertically
  254.             param  num_refs  the number of references being used for the frame
  255.         */
  256.         MEData( const int xnumMB, const int ynumMB , 
  257.                 const int xnumblocks, const int ynumblocks , const int num_refs = 2);
  258.         //! Constructor
  259.         /*! 
  260.             Constructor. Numbers of blocks derived from the number of MBs
  261.             param  xnumMB  the number of MBs horizontally
  262.             param  ynumMB  the number of MBs vertically
  263.             param  num_refs  the number of references being used for the frame
  264.         */
  265.         MEData( const int xnumMB, const int ynumMB , const int num_refs = 2);
  266.         //! Destructor
  267.         ~MEData();
  268.         //! Get the block cost structures for each reference
  269.         TwoDArray<MvCostData>& PredCosts(const int ref_id){ return *( m_pred_costs[ref_id] ); }
  270.         //! Get the block cost structures for each reference
  271.         const TwoDArray<MvCostData>& PredCosts(const int ref_id) const { return *( m_pred_costs[ref_id] ); }
  272.         //! Get the intra costs
  273.         TwoDArray<float>& IntraCosts(){ return m_intra_costs; }
  274.         //! Get the intra costs
  275.         const TwoDArray<float>& IntraCosts() const { return m_intra_costs; }
  276.         //! Get the bipred costs
  277.         TwoDArray<MvCostData>& BiPredCosts(){ return m_bipred_costs; }
  278.         //! Get the bipred costs
  279.         const TwoDArray<MvCostData>& BiPredCosts() const { return m_bipred_costs; }
  280.         //! Get the MB costs
  281.         TwoDArray<float>& MBCosts(){ return m_MB_costs; }
  282.         //! Get the MB costs
  283.         const TwoDArray<float>& MBCosts() const { return m_MB_costs; }
  284.         //! Set up the lambda map by detecting motion discontinuities 
  285.         void SetLambdaMap( const int num_refs , const float lambda );
  286.         //! Set up the lambda map by averaging the lambda map from a lower level 
  287.         void SetLambdaMap( const int level , const TwoDArray<float>& l_map , const float wt );
  288.         //! Get a lambda value for a given block and level
  289.         const TwoDArray<float>& LambdaMap() const { return m_lambda_map; }
  290.         //! Get the inliers for each reference
  291.         TwoDArray<int>& GlobalMotionInliers(const int ref_id){ return *( m_inliers[ref_id] ); }
  292.         //! Get the inliers for each reference
  293.         const TwoDArray<int>& GlobalMotionInliers(const int ref_id) const { return *( m_inliers[ref_id] ); }
  294.         //! Overloaded operator<< for outputing to (file) stream
  295.         friend std::ostream &operator<< (std::ostream & stream, MEData & me_data);
  296.         //! Overloaded operator>> for input of data from (file) stream
  297.         friend std::istream &operator>> (std::istream & stream, MEData & me_data);
  298.     private:
  299.         // Initialises the arrays of data
  300.         void InitMEData();
  301.         // Finds transitions in the motion vectors
  302.         void FindTransitions( TwoDArray<bool>& trans_map , const int ref_num );
  303.         // The costs of predicting each block, for each reference
  304.         OneDArray< TwoDArray<MvCostData>* > m_pred_costs;
  305.         // The costs of predicting each block by DC
  306.         TwoDArray<float> m_intra_costs;
  307.         // The costs of predicting each block bidirectionally
  308.         TwoDArray<MvCostData> m_bipred_costs;
  309.         // The costs for each macroblock as a whole
  310.         TwoDArray<float> m_MB_costs;
  311.         // A map of the lambda values to use
  312.         TwoDArray<float> m_lambda_map;
  313.         // Global motion inliers
  314.         OneDArray< TwoDArray<int>* > m_inliers;
  315.     };
  316.     //motion estimation and coding stuff
  317.     //! Return the median of three motion vectors 
  318.     inline MVector MvMedian(const MVector& mv1,const MVector& mv2,const MVector& mv3) {
  319.         //takes median of each vector component    
  320.         MVector tmp_mv;
  321.         tmp_mv.x=mv1.x;
  322.         tmp_mv.x+=mv2.x;
  323.         tmp_mv.x+=mv3.x;
  324.         tmp_mv.x-=std::max(std::max(mv1.x,mv2.x),mv3.x);
  325.         tmp_mv.x-=std::min(std::min(mv1.x,mv2.x),mv3.x);
  326.         tmp_mv.y=mv1.y;
  327.         tmp_mv.y+=mv2.y;
  328.         tmp_mv.y+=mv3.y;
  329.         tmp_mv.y-=std::max(std::max(mv1.y,mv2.y),mv3.y);
  330.         tmp_mv.y-=std::min(std::min(mv1.y,mv2.y),mv3.y);
  331.         return tmp_mv;
  332.     }
  333.     //! Return the median of a set of motion vectors 
  334.     inline MVector MvMedian(const std::vector<MVector>& vect_list){
  335.         //more general median. Takes the median of each vector component    
  336.         MVector median;
  337.         int num_vals=int(vect_list.size());
  338.         if (num_vals>0)    {
  339.             int pos=0;
  340.             std::vector<int> ordered_vals(vect_list.size());
  341.             //do x first
  342.             ordered_vals[0]=vect_list[0].x;        
  343.             for (int I=1;I<num_vals;++I){
  344.                 for (int K=0;K<I;++K){
  345.                     if (vect_list[I].x<ordered_vals[K]){
  346.                         pos=K;
  347.                         break;
  348.                     }
  349.                     else
  350.                         pos=K+1;
  351.                 }//K
  352.                 if (pos==I)
  353.                     ordered_vals[I]=vect_list[I].x;
  354.                 else{
  355.                     for (int K=pos;K>=I-1;--K){
  356.                         ordered_vals[K+1]=ordered_vals[K];
  357.                     }
  358.                     ordered_vals[pos]=vect_list[I].x;
  359.                 }
  360.             }//I
  361.             if (vect_list.size()%2!=0)
  362.                 median.x=ordered_vals[(num_vals-1)/2];
  363.             else
  364.                 median.x=(ordered_vals[(num_vals/2)-1]+ordered_vals[num_vals/2])/2;
  365.             //now do y
  366.             ordered_vals[0]=vect_list[0].y;        
  367.             for (int I=1;I<num_vals;++I){
  368.                 for (int K=0;K<I;++K){
  369.                     if (vect_list[I].y<ordered_vals[K]){
  370.                         pos=K;
  371.                         break;
  372.                     }
  373.                     else
  374.                         pos=K+1;
  375.                 }//K
  376.                 if (pos==I)
  377.                     ordered_vals[I]=vect_list[I].y;
  378.                 else{
  379.                     for (int K=pos;K>=I-1;--K){
  380.                         ordered_vals[K+1]=ordered_vals[K];
  381.                     }
  382.                     ordered_vals[pos]=vect_list[I].y;
  383.                 }
  384.             }//I
  385.             if (num_vals%2!=0)
  386.                 median.y=ordered_vals[(num_vals-1)/2];
  387.             else
  388.                 median.y=(ordered_vals[(num_vals/2)-1]+ordered_vals[num_vals/2])/2;        
  389.         }
  390.         else{
  391.             median.x=0;
  392.             median.y=0;
  393.         }
  394.         return median;
  395.     }
  396.     //! Return the mean of two motion vectors
  397.     inline MVector MvMean(MVector& mv1,MVector& mv2) {
  398.         //takes median of each vector component    
  399.         MVector tmp_mv;
  400.         tmp_mv.x=mv1.x;
  401.         tmp_mv.x+=mv2.x;
  402.         tmp_mv.x/=2;
  403.         tmp_mv.y=mv1.y;
  404.         tmp_mv.y+=mv2.y;
  405.         tmp_mv.y/=2;
  406.         return tmp_mv;
  407.     }
  408.     //! Return the squared length of a motion vector
  409.     inline int Norm2(const MVector& mv){//L^2 norm of a motion vector
  410.         return mv.x*mv.x+mv.y*mv.y;
  411.     }
  412.     //! Return the sum of the lengths of a motion vector's componets
  413.     inline int Norm1(const MVector& mv){//L^1 norm of a motion vector
  414.         return abs(mv.x)+abs(mv.y);
  415.     }
  416.     //! Return the mean of a set of integer values
  417.     inline int GetMean(std::vector<int>& values){
  418.         int sum=0;
  419.         for (unsigned int I=0;I<values.size();++I)
  420.             sum+=values[I];
  421.         sum/=int(values.size());
  422.         return sum;
  423.     }
  424.     //! Return the mean of a set of unsigned integer values
  425.     inline unsigned int GetMean(std::vector<unsigned int>& values){
  426.         int sum=0;
  427.         for (unsigned int I=0;I<values.size();++I)
  428.             sum+=values[I];
  429.         sum+=(values.size()>>1);
  430.         sum/=values.size();
  431.         return sum;
  432.     }
  433. } // namespace dirac
  434. #endif