www.pudn.com > motionE.zip.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,
unsigned char *oldref,
unsigned char *cur,
int sxf, int syf,mbinfo *mbi)
{
int i, j;
height=pictInform.height;
width =pictInform.width;
SearchRule=pictInform.SearchRule;
MPCThred =pictInform.MPCThred;

//遍历picture中所有宏块
for (j=0; j<height; j+=16)
for (i=0; i<width; i+=16) //width height 是图像尺寸
{ //预测出当前帧 cur
frame_ME(oldorg,oldref,cur,i,j,sxf,syf,mbi);
mbi++;
}
}

//帧估计
//包括多种搜索方法和搜索准则
//LK_ME Fullsearch logsearch JC1 JC2
//搜索准则:dist1 MSE
void CMotion::frame_ME(unsigned char *oldorg,unsigned char *oldref,
unsigned char *cur, int i, int j, int sxf,
int syf, mbinfo *mbi)
{
int imin,jmin;//位移 其值是相对与(0,0)位置的偏差
int iblkVar,iVarNmc; //块的均方差
int dmc,vmc; //
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==(pictInform.mb_width-1)*16)//去掉边界的宏块
{
x1=0;
y1=0;
}
if(j!=0)//确定y方向
{
x2=(mbi-pictInform.mb_width)->MV[0];
y2=(mbi-pictInform.mb_width)->MV[1];
}
if(j==0||j==(pictInform.mb_height-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&amt;&amt;dety<=1)//更新搜索范围
{
sxf=sxf-1;
syf=syf-1;
}


dmc = TSS(oldorg,oldref,mb,
width,i+detx,j+dety,sxf,syf,16,width,height,&amt;imin,&amt;jmin);

int sad;
sad=MAD(oldref+(imin>>1)+width*(jmin>>1),mb,width,0,0,16,65536);
if(((i-imin>>1)==0)&amt;&amt;((j-jmin>>1)==0))//0运动矢量
sad=sad-100;
mbi->mb_type=INTER;
mbi->MV[0] = imin - (i<<1); //附给运动矢量以半象素为单位
mbi->MV[1] = jmin - (j<<1);

}




/*绝对值差
* 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 &amt;&amt; !hy)
for (j=0; j<h; j++)
{
for(i=0;i<16;i++)
{
v=p1[i]-p2[i];
s+=abs(v);
}
if(s >= distlim)
break;
p1+= lx;
p2+= lx;
}
else if (hx &amt;&amt; !hy)
for (j=0; j<h; j++)
{
for (i=0; i<16; i++)
{
v = ((unsigned int)(p1[i]+p1[i+1]+1)>>1) - p2[i];
s+=abs(v); //插值(a+b+1)/2
}
p1+= lx;
p2+= lx;
}
else if (!hx &amt;&amt; hy)//y方向上插值
{
p1a = p1 + lx;//下一行
for (j=0; j<h; j++)
{
for (i=0; i<16; i++)
{
v = ((unsigned int)(p1[i]+p1a[i]+1)>>1) - p2[i];
s+=abs(v);
}
p1 = p1a;
p1a+= lx;
p2+= lx;
}
}
else //if (hx &amt;&amt; hy) x y方向上都插值
{
p1a = p1 + lx;
for (j=0; j<h; j++)
{
for (i=0; i<16; i++)
{
v = ((unsigned int)(p1[i]+p1[i+1]+p1a[i]+p1a[i+1]+2)>>2) - p2[i];
s+=abs(v);
}
p1 = p1a;
p1a+= lx;
p2+= lx;
}
}
return s;
}

int CMotion::TSS(unsigned char *org, unsigned char *ref,
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 &amt;&amt; i<=ihigh &amt;&amt; j>=jlow &amt;&amt; j<=jhigh)

d = MAD(org+i+lx*j,blk,lx,0,0,h,dmin);



if (d<dmin)
{
dmin = d;
imin = i;
jmin = j;
}
}

if (k<2) i+=l; //仅搜索周围8个点 * * * l间距
else if (k<4) j+=l; // * # *
else if (k<6) i-=l; // * * *
else j-=l; //
}
}

//半象素搜索
//用重构图像进行搜索

dmin=65536;

imin <<= 1;
jmin <<= 1;
ilow = imin - (imin>0);
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(ref+(i>>1)+lx*(j>>1),blk,lx,i&amt;1,j&amt;1,h,dmin);

if (d<dmin)
{
dmin = d;
imin = i;
jmin = j;
}
}

*iminp = imin;
*jminp = jmin;

return dmin;
}