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