motion.h

00001 /* ***** BEGIN LICENSE BLOCK *****
00002 *
00003 * $Id: motion.h,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 #include <libdirac_common/common.h>
00039 #include <algorithm>
00040 #ifndef _MOTION_H
00041 #define _MOTION_H
00042 
00043 namespace dirac
00044 {
00046     //classes and functions for motion estimation and compensation//
00048 
00049     //classes
00050 
00052     template <class T>
00053     class MotionVector
00054     {
00055     public:
00056 
00058         MotionVector<T>(T a, T b) : x(a), y(b) {};
00060         MotionVector<T>() : x(0), y(0) {};
00062         MotionVector<T>(T a) : x(a), y(a) {};
00063 
00065         inline MotionVector<T> operator+(const MotionVector<T>& argument) const;
00066 
00068         inline MotionVector<T> operator-(const MotionVector<T>& argument) const;
00069 
00071         inline MotionVector<T> operator*(const float argument) const;
00072 
00074         inline MotionVector<T> operator*(const int argument) const;
00075 
00077         inline MotionVector<T> operator<<(const int argument) const;
00078 
00080         inline MotionVector<T> operator>>(const int argument) const;
00081 
00082 
00084         T x,y;
00085 
00086     };
00087 
00088 
00089     template <class T>
00090     inline MotionVector<T> MotionVector<T>::operator+(const MotionVector<T>& argument) const 
00091     {
00092         MotionVector<T> temp;
00093         temp.x = x + argument.x;
00094         temp.y = y + argument.y;
00095 
00096         return temp;
00097     }
00098 
00099     template <class T>
00100     inline MotionVector<T>  MotionVector<T>::operator-(const MotionVector<T>& argument) const 
00101     {
00102         MotionVector<T> temp;
00103         temp.x = x-argument.x;
00104         temp.y = y-argument.y;
00105 
00106         return temp;
00107     }
00108 
00109     template <class T>
00110     inline MotionVector<T>  MotionVector<T>::operator*(const float argument) const 
00111     {
00112         MotionVector<T> temp;
00113         temp.x = x*argument;
00114         temp.y = y*argument;
00115 
00116         return temp;
00117     }
00118 
00119     template <class T>
00120     inline MotionVector<T>  MotionVector<T>::operator*(const int argument) const 
00121     {
00122         MotionVector<T> temp;
00123         temp.x = x*argument;
00124         temp.y = y*argument;
00125 
00126         return temp;
00127     }
00128 
00129     template <class T>
00130     inline MotionVector<T>  MotionVector<T>::operator<<(const int argument) const 
00131     {
00132         MotionVector<T> temp;
00133         temp.x = x<<argument;
00134         temp.y = y<<argument;
00135 
00136         return temp;
00137     }
00138 
00139     template <class T>
00140     inline MotionVector<T>  MotionVector<T>::operator>>(const int argument) const 
00141     {
00142         MotionVector<T> temp;
00143         temp.x = x>>argument;
00144         temp.y = y>>argument;
00145 
00146         return temp;
00147     }
00148 
00150     template <class T>
00151     std::ostream & operator<< (std::ostream & stream, MotionVector<T> & mv)
00152     {
00153         stream << mv.x << " " << mv.y;
00154 
00155         return stream;
00156     }
00157 
00159     template <class T>
00160     std::istream & operator>> (std::istream & stream, MotionVector<T> & mv)
00161     {
00162         stream >> mv.x;
00163         stream >> mv.y;
00164 
00165         return stream;
00166     }
00167 
00169     typedef MotionVector<int> MVector;
00170 
00172     typedef MotionVector<int> ImageCoords;
00173 
00175     typedef TwoDArray<MVector> MvArray;
00176 
00178     typedef TwoDArray< MotionVector<float> > MvFloatArray;
00179 
00181     class MvCostData
00182     {
00183     public:
00185         MvCostData():
00186         SAD(0.0),
00187         mvcost(0.0),
00188         total(0.0){}
00189 
00190         void SetTotal( const float lambda ){total = SAD + lambda*mvcost;}
00191 
00193         float SAD;
00194 
00196         float mvcost;
00197 
00199         float total;
00200     };
00201 
00202 
00204 
00208     class MvData
00209     {
00210     public:
00212 
00220         MvData( const int xnumMB, int ynumMB , 
00221                 const int xnumblocks, int ynumblocks ,  const int num_refs = 2);
00222 
00224 
00230         MvData( const int xnumMB, int ynumMB ,  const int num_refs = 2);
00231 
00233         ~MvData();
00234 
00236         MvArray& Vectors(const int ref_id){return *( m_vectors[ref_id] );}
00237 
00239         const MvArray& Vectors(const int ref_id) const {return *( m_vectors[ref_id] );}
00240 
00242         MvArray& GlobalMotionVectors(const int ref_id){return *( m_gm_vectors[ref_id] );}
00243 
00245         const MvArray& GlobalMotionVectors(const int ref_id) const {return *( m_gm_vectors[ref_id] );} 
00246 
00248         TwoDArray<ValueType>& DC(CompSort cs){return *( m_dc[cs] );}
00249 
00251         const TwoDArray<ValueType>& DC(CompSort cs) const {return *( m_dc[cs] );}
00252 
00254         const OneDArray< TwoDArray<ValueType>* >& DC() const {return m_dc;}
00255 
00257         TwoDArray<PredMode>& Mode(){return m_modes;}
00258 
00260         const TwoDArray<PredMode>& Mode() const {return m_modes;}
00261      
00263         TwoDArray<int>& MBSplit(){return m_mb_split;}
00264 
00266         const TwoDArray<int>& MBSplit() const{return m_mb_split;}
00267 
00269         TwoDArray<bool>& MBCommonMode(){return m_mb_common;}
00270 
00272         const TwoDArray<bool>& MBCommonMode() const{return m_mb_common;}
00273 
00275         OneDArray<float>& GlobalMotionParameters(const int ref_id) { return *( m_gm_params[ref_id] ); }
00276 
00278         const OneDArray<float>& GlobalMotionParameters(const int ref_id) const { return *( m_gm_params[ref_id] ); }
00279 
00280     private:
00281         // Initialises the arrays of data
00282         void InitMvData();
00283 
00284         // The motion vectors
00285         OneDArray<MvArray*> m_vectors;
00286 
00287         // The global motion vectors
00288         OneDArray<MvArray*> m_gm_vectors;
00289 
00290         // The block modes
00291         TwoDArray<PredMode> m_modes;
00292 
00293         // The DC values
00294         OneDArray< TwoDArray<ValueType>* > m_dc;
00295 
00296         // The MB split levels
00297         TwoDArray<int> m_mb_split;
00298 
00299         // The MB common mode indicators 
00300         TwoDArray<bool> m_mb_common;
00301 
00302         // Global motion model parameters
00303         OneDArray< OneDArray<float>* > m_gm_params;
00304     };
00305 
00307 
00312     class MEData: public MvData
00313     {
00314     public:
00315 
00317 
00325         MEData( const int xnumMB, const int ynumMB , 
00326                 const int xnumblocks, const int ynumblocks , const int num_refs = 2);
00327 
00329 
00335         MEData( const int xnumMB, const int ynumMB , const int num_refs = 2);
00336 
00338         ~MEData();
00339 
00341         TwoDArray<MvCostData>& PredCosts(const int ref_id){ return *( m_pred_costs[ref_id] ); }
00342 
00344         const TwoDArray<MvCostData>& PredCosts(const int ref_id) const { return *( m_pred_costs[ref_id] ); }
00345 
00347         TwoDArray<float>& IntraCosts(){ return m_intra_costs; }
00348 
00350         const TwoDArray<float>& IntraCosts() const { return m_intra_costs; }
00351 
00353         TwoDArray<MvCostData>& BiPredCosts(){ return m_bipred_costs; }
00354 
00356         const TwoDArray<MvCostData>& BiPredCosts() const { return m_bipred_costs; }
00357 
00359         TwoDArray<float>& MBCosts(){ return m_MB_costs; }
00360 
00362         const TwoDArray<float>& MBCosts() const { return m_MB_costs; }
00363 
00365         void SetLambdaMap( const int num_refs , const float lambda );
00366 
00368         void SetLambdaMap( const int level , const TwoDArray<float>& l_map , const float wt );
00369 
00371         const TwoDArray<float>& LambdaMap() const { return m_lambda_map; }
00372 
00374         TwoDArray<int>& GlobalMotionInliers(const int ref_id){ return *( m_inliers[ref_id] ); }
00375 
00377         const TwoDArray<int>& GlobalMotionInliers(const int ref_id) const { return *( m_inliers[ref_id] ); }
00378 
00380         friend std::ostream &operator<< (std::ostream & stream, MEData & me_data);
00381 
00383         friend std::istream &operator>> (std::istream & stream, MEData & me_data);
00384 
00385     private:
00386         // Initialises the arrays of data
00387         void InitMEData();
00388 
00389         // Finds transitions in the motion vectors
00390         void FindTransitions( TwoDArray<bool>& trans_map , const int ref_num );
00391 
00392         // The costs of predicting each block, for each reference
00393         OneDArray< TwoDArray<MvCostData>* > m_pred_costs;
00394 
00395         // The costs of predicting each block by DC
00396         TwoDArray<float> m_intra_costs;
00397 
00398         // The costs of predicting each block bidirectionally
00399         TwoDArray<MvCostData> m_bipred_costs;
00400 
00401         // The costs for each macroblock as a whole
00402         TwoDArray<float> m_MB_costs;
00403 
00404         // A map of the lambda values to use
00405         TwoDArray<float> m_lambda_map;
00406 
00407         // Global motion inliers
00408         OneDArray< TwoDArray<int>* > m_inliers;
00409 
00410     };
00411 
00412     //motion estimation and coding stuff
00413 
00415     inline MVector MvMedian(const MVector& mv1,const MVector& mv2,const MVector& mv3) {
00416         //takes median of each vector component    
00417         MVector tmp_mv;
00418 
00419         tmp_mv.x=mv1.x;
00420         tmp_mv.x+=mv2.x;
00421         tmp_mv.x+=mv3.x;
00422 
00423         tmp_mv.x-=std::max(std::max(mv1.x,mv2.x),mv3.x);
00424         tmp_mv.x-=std::min(std::min(mv1.x,mv2.x),mv3.x);
00425 
00426         tmp_mv.y=mv1.y;
00427         tmp_mv.y+=mv2.y;
00428         tmp_mv.y+=mv3.y;
00429 
00430         tmp_mv.y-=std::max(std::max(mv1.y,mv2.y),mv3.y);
00431         tmp_mv.y-=std::min(std::min(mv1.y,mv2.y),mv3.y);
00432 
00433         return tmp_mv;
00434     }
00435 
00437     inline MVector MvMedian(const std::vector<MVector>& vect_list){
00438         //more general median. Takes the median of each vector component    
00439 
00440         MVector median;
00441         int num_vals=int(vect_list.size());
00442         if (num_vals>0)    {
00443             int pos=0;
00444             std::vector<int> ordered_vals(vect_list.size());
00445             //do x first
00446             ordered_vals[0]=vect_list[0].x;        
00447             for (int I=1;I<num_vals;++I){
00448                 for (int K=0;K<I;++K){
00449                     if (vect_list[I].x<ordered_vals[K]){
00450                         pos=K;
00451                         break;
00452                     }
00453                     else
00454                         pos=K+1;
00455                 }//K
00456                 if (pos==I)
00457                     ordered_vals[I]=vect_list[I].x;
00458                 else{
00459                     for (int K=pos;K>=I-1;--K){
00460                         ordered_vals[K+1]=ordered_vals[K];
00461                     }
00462                     ordered_vals[pos]=vect_list[I].x;
00463                 }
00464             }//I
00465             if (vect_list.size()%2!=0)
00466                 median.x=ordered_vals[(num_vals-1)/2];
00467             else
00468                 median.x=(ordered_vals[(num_vals/2)-1]+ordered_vals[num_vals/2])/2;
00469 
00470             //now do y
00471             ordered_vals[0]=vect_list[0].y;        
00472             for (int I=1;I<num_vals;++I){
00473                 for (int K=0;K<I;++K){
00474                     if (vect_list[I].y<ordered_vals[K]){
00475                         pos=K;
00476                         break;
00477                     }
00478                     else
00479                         pos=K+1;
00480                 }//K
00481                 if (pos==I)
00482                     ordered_vals[I]=vect_list[I].y;
00483                 else{
00484                     for (int K=pos;K>=I-1;--K){
00485                         ordered_vals[K+1]=ordered_vals[K];
00486                     }
00487                     ordered_vals[pos]=vect_list[I].y;
00488                 }
00489             }//I
00490             if (num_vals%2!=0)
00491                 median.y=ordered_vals[(num_vals-1)/2];
00492             else
00493                 median.y=(ordered_vals[(num_vals/2)-1]+ordered_vals[num_vals/2])/2;        
00494 
00495         }
00496         else{
00497             median.x=0;
00498             median.y=0;
00499         }
00500         return median;
00501     }
00502 
00504     inline MVector MvMean(MVector& mv1,MVector& mv2) {
00505         //takes median of each vector component    
00506         MVector tmp_mv;
00507 
00508         tmp_mv.x=mv1.x;
00509         tmp_mv.x+=mv2.x;
00510         tmp_mv.x/=2;
00511 
00512         tmp_mv.y=mv1.y;
00513         tmp_mv.y+=mv2.y;
00514         tmp_mv.y/=2;
00515 
00516         return tmp_mv;
00517     }
00518 
00520     inline int Norm2(const MVector& mv){//L^2 norm of a motion vector
00521         return mv.x*mv.x+mv.y*mv.y;
00522     }
00523 
00525     inline int Norm1(const MVector& mv){//L^1 norm of a motion vector
00526         return abs(mv.x)+abs(mv.y);
00527     }
00528 
00530     inline int GetMean(std::vector<int>& values){
00531         int sum=0;
00532         for (unsigned int I=0;I<values.size();++I)
00533             sum+=values[I];
00534         sum/=int(values.size());
00535         return sum;
00536     }
00537 
00539     inline unsigned int GetMean(std::vector<unsigned int>& values){
00540         int sum=0;
00541         for (unsigned int I=0;I<values.size();++I)
00542             sum+=values[I];
00543         sum+=(values.size()>>1);
00544         sum/=values.size();
00545         return sum;
00546     }
00547 
00548 } // namespace dirac
00549 
00550 #endif

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