www.pudn.com > MotionEstimation.rar > Motion.cpp


// Motion.cpp: implementation of the CMotion class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "Motion.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
// extern  PICTINFO pictInform; 
// extern int Pquant; 
// extern  CFile Statisfile; 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CMotion::CMotion() 
{ 
 
 
} 
 
CMotion::~CMotion() 
{ 
 
} 
//用原图像进行全象素搜索       /用重构图像进行半象素搜索 
/*                    
 * oldorg: 源帧 (for P and B frames) 
 * oldref: 重构帧 (P and B frames) 
 * cur:    当前帧:  预测形成帧 
 * sxf,syf: 前向搜索窗 (frame coordinates) 
 * mbi:     指向宏块结构的指针 
 * 返回结果: 确定宏块的信息结构 mbi 
 */ 
 
void CMotion::motion_estimation(unsigned char *oldorg, int width, int height, unsigned char *cur,unsigned char *reconframe, unsigned char *pdata, int sxf, int syf, mbinfo *mbi) 
{ 
	int i, j; 
  int x, y; 
   
//   mbi->MV[0]=0; 
//   mbi->MV[1]=0; 
//   height=pictInform.height; 
//   width =pictInform.width; 
//   SearchRule=pictInform.SearchRule; 
//   MPCThred  =pictInform.MPCThred; 
 
  //遍历picture中所有宏块  
  for (j=0; jMV[1] + x)*width + (i+mbi->MV[0] + y)]; 
   	        pdata[(j + x)*width + (i + y)]=oldorg[(j + x)*width + (i + y)]-cur[(j+mbi->MV[1] + x)*width + (i+mbi->MV[0] + y)]; 
			   
		  } 
	   
	  mbi++; 
    } 
 
} 
 
 
//帧估计 
//包括多种搜索方法和搜索准则 
//LK_ME  Fullsearch  logsearch   JC1  JC2   
//搜索准则:dist1  MSE       
void CMotion::frame_ME(unsigned char *oldorg,int width,int height,  
					   unsigned char *cur, int i, int j, int sxf,  
					   int syf, mbinfo *mbi) 
{ 
  int imin,jmin;//位移 其值是相对与(0,0)位置的偏差 
//   int iblkVar,iVarNmc;   //块的均方差 
//  int dmc,vmc;   
  int dmc; 
  unsigned char *mb; 
  mb = cur + i + width*j;//宏块的位置 
//  iblkVar = variance(mb,width);//计算每一块的偏差 
//***************计算参考矢量**************  
  //参考矢量偏差 
     int x1,x2,y1,y2; 
	 if(i!=0)//确定x方向 
	 { 
		 x1=(*(mbi-1)).MV[0]; 
		 y1=(*(mbi-1)).MV[1]; 
	 } 
	 if(i==0||i==(width/16-1)*16)//去掉边界的宏块 
	 { 
		 x1=0; 
		 y1=0; 
	 } 
	 if(j!=0)//确定y方向 
	 {		 
		 x2=(*(mbi-width/16)).MV[0]; 
		 y2=(*(mbi-width/16)).MV[1]; 
	 } 
	 if(j==0||j==(height/16-1)*16)//去掉边界的宏块 
	 { 
		 x2=0; 
		 y2=0; 
	 } 
	 x1=x1>>1; //仅取运动矢量的整像素的位置 
	 x2=x2>>1; 
	 y1=y1>>1; 
	 y2=y2>>1; 
	 int detx,dety;  //取两个运动矢量的平均作为参考矢量 
     detx=(x1+x2)/2; 
	 dety=(y1+y2)/2; 
     if(detx<=1&&dety<=1)//更新搜索范围 
	 { 
		 sxf=sxf-1; 
		 syf=syf-1; 
	 } 
 
 
   dmc = TSS(oldorg,mb, 
        width,i+detx,j+dety,sxf,syf,16,width,height,&imin,&jmin);    
		 
//     int sad; 
// 	sad=MAD(oldref+(imin>>1)+width*(jmin>>1),mb,width,0,0,16,65536); 
// 	if(((i-imin>>1)==0)&&((j-jmin>>1)==0))//0运动矢量 
// 		sad=sad-100; 
//    mbi->mb_type=INTER; 
    (*mbi).MV[0] = -((imin)-i); //附给运动矢量以整象素为单位 
    (*mbi).MV[1] = -((jmin)-j); 
 
} 
 
 
 
 
/*绝对值差 
 * total absolute difference between two (16*h) blocks 
 * including optional half pel interpolation of blk1 (hx,hy) 
 * blk1,blk2: addresses of top left pels of both blocks 
 * lx:        distance (in bytes) of vertically adjacent pels 
 * hx,hy:     flags for horizontal and/or vertical interpolation 
 * h:         height of block (usually 8 or 16) 
 * distlim:   bail out if sum exceeds this value 
 */ 
int CMotion::MAD(unsigned char *blk1, unsigned char *blk2,  
				   int lx, int hx, int hy, int h, int distlim) 
{ 
  unsigned char *p1,*p2,*p1a;        //MAD 
  int i,j; 
  int s,v; 
 
  s = 0; 
  p1 = blk1; 
  p2 = blk2; 
 
  if (!hx && !hy) 
    for (j=0; j= distlim) 
         break; 
      p1+= lx; 
      p2+= lx; 
	  } 
  else if (hx && !hy) 
    for (j=0; j>1) - p2[i]; 
        s+=abs(v);          //插值(a+b+1)/2 
	  } 
      p1+= lx; 
      p2+= lx; 
    } 
  else if (!hx && hy)//y方向上插值 
  { 
    p1a = p1 + lx;//下一行 
    for (j=0; j>1) - p2[i]); 
        s+=abs(v); 
	  } 
      p1 = p1a; 
      p1a+= lx; 
      p2+= lx; 
    } 
  } 
  else //if (hx && hy) x y方向上都插值 
  { 
    p1a = p1 + lx; 
    for (j=0; j>2) - p2[i]; 
        s+=abs(v); 
	  } 
      p1 = p1a; 
      p1a+= lx; 
      p2+= lx; 
    } 
  } 
  return s; 
} 
 
int CMotion::TSS(unsigned char *org, 
					   unsigned char *blk, int lx, int i0, int j0,  
					   int sx, int sy, int h, int xmax, int ymax,  
					   int *iminp, int *jminp) 
{ 
  
  int i,j,imin,jmin,ilow,ihigh,jlow,jhigh; 
  int d,dmin; 
  int k,l,sxy; 
 
  ilow  = i0 - sx; 
  ihigh = i0 + sx; 
  if (ilow<0) 
    ilow = 0; 
  if (ihigh>xmax-16) 
    ihigh = xmax-16; 
 
  jlow  = j0 - sy; 
  jhigh = j0 + sy; 
  if (jlow<0) 
    jlow = 0; 
  if (jhigh>ymax-h) 
    jhigh = ymax-h; 
 
  //全象素搜索, spiraling outwards 
  //用原图像做全象素搜索, 
  imin = i0; 
  jmin = j0; 
 
   
  dmin = MAD(org+imin+lx*jmin,blk,lx,0,0,h,65536); 
 
 
  sxy = (sx>sy) ? sx : sy; 
 
  for (l=sxy; l>0; l>>=1)//减小搜索半径 
  { 
    i = imin - l; 
    j = jmin - l; 
    for (k=0; k<8; k++)    //搜索周围8个点 
    { 
      if (i>=ilow && i<=ihigh && j>=jlow && j<=jhigh) 
       
	    d = MAD(org+i+lx*j,blk,lx,0,0,h,dmin); 
		  
	 
 
        if (d0);  
  ihigh = imin + (imin<((xmax-16)<<1)); 
  jlow = jmin - (jmin>0); 
  jhigh = jmin + (jmin<((ymax-h)<<1)); 
 
  for (j=jlow; j<=jhigh; j++) 
    for (i=ilow; i<=ihigh; i++) 
    { 
 
   	d = MAD(org+(i>>1)+lx*(j>>1),blk,lx,i&1,j&1,h,dmin);		 
 
      if (d