📄 fullsearch.cpp
字号:
#include <iostream.h>
//#include <iomanip.h>
#include <math.h>
#include <stdio.h>
#include <time.h>
#define T 0
const unsigned short int height=288;
const unsigned short int width=352;
unsigned short int yMax=height-16;
unsigned short int xMax=width-16;
unsigned char CurrentFrame[height][width];
unsigned char RefFrame[height][width];
unsigned char RefOrgFrame[height][width];
unsigned char *PCurrentFrame=&CurrentFrame[0][0];
unsigned char *PRefFrame=&RefFrame[0][0];
unsigned char *PRefOrgFrame=&RefOrgFrame[0][0];
unsigned char *PSwitchFrame;
FILE *Yuv_file,*ReconImage;
unsigned int frameNO;
unsigned int frameNOMax=50;
struct MotInfo{
int xoff;
int yoff;
};
MotInfo MVList1[height/16][width/16];
MotInfo *CurMV=&MVList1[0][0]; //指向当前帧运动矢量矩阵的指针
void frame_ME(int,int);
void FullSearch(int,int,int&,int&,unsigned int&,int&);
unsigned int SadFun(int,int,int,int);
int kSum=0; //每帧图像总的搜索点
int KSUM=0; //所有压缩图像的搜索点数
float kAverage=0; //每帧中每块的平均搜索点数
float KAVERAGE=0; //每帧的平均搜索点数
float msesum=0;
float mse=0;
float MSESUM=0;
float psnr=0;
float PSNR=0;
void main()
{
if((Yuv_file=fopen("d:\\sequense\\mobile.yuv","rb"))==NULL){//foreman.yuvmother_daughter.yuv"akiyo_cif.yuv""vectra.yuv""mobile.yuv"
printf("cannot open this file0\n");
}
if((ReconImage=fopen("recon.yuv","wb"))==NULL){
printf("cannot open this file1\n");
}
fread(PRefOrgFrame,sizeof(unsigned char),288*352,Yuv_file);
fseek(Yuv_file,sizeof(unsigned char)*352*288/2,1);
fread(PCurrentFrame,sizeof(unsigned char),288*352,Yuv_file);
int i,j;
for(i=0;i<height;i+=16) //行,y方向
for(j=0;j<width;j+=16) //列,x方向
{
frame_ME(i,j);
CurMV++;
}
CurMV=&MVList1[0][0];
KSUM+=kSum;
kAverage=(float)kSum/396;
for(i=0;i<height;i+=16) //行
for(j=0;j<width;j+=16) //列
{
for(int m=0;m<16;m++)
for(int n=0;n<16;n++)
{
RefFrame[i+m][j+n]=RefOrgFrame[i+CurMV->yoff+m][j+CurMV->xoff+n];
} //预测图像
CurMV++;
}
CurMV=&MVList1[0][0];
for(i=0;i<height;i++) //行
for(j=0;j<width;j++) //列
{
msesum+=(CurrentFrame[i][j]-RefFrame[i][j])*(CurrentFrame[i][j]-RefFrame[i][j]);}
mse=msesum/(288*352);
psnr=10*log10(255*255/mse);
MSESUM+=msesum;
fwrite(RefFrame,sizeof(unsigned char),288*352,ReconImage);
cout<<"第2帧:"<<psnr<<";"<<"平均搜索点数是:"<<kAverage<<endl;
for(frameNO=3;frameNO<=frameNOMax;frameNO++)
{
msesum=0;
mse=0;
psnr=0;
kAverage=0;
kSum=0;
PSwitchFrame=PCurrentFrame;
PCurrentFrame=PRefOrgFrame;
PRefOrgFrame=PSwitchFrame;
fseek(Yuv_file,sizeof(unsigned char)*352*288/2,1);
fread(PCurrentFrame,sizeof(unsigned char),288*352,Yuv_file);
for(i=0;i<height;i+=16) //行,y方向
for(j=0;j<width;j+=16) //列,x方向
{
frame_ME(i,j);
CurMV++;
}
CurMV=&MVList1[0][0];
KSUM+=kSum;
kAverage=(float)kSum/396;
for(i=0;i<height;i+=16) //行
for(j=0;j<width;j+=16) //列
{
for(int m=0;m<16;m++)
for(int n=0;n<16;n++)
{
RefFrame[i+m][j+n]=RefOrgFrame[i+CurMV->yoff+m][j+CurMV->xoff+n];
} //预测图像
CurMV++;
}
CurMV=&MVList1[0][0];
for(i=0;i<height;i++) //行
for(j=0;j<width;j++) //列
{
msesum+=(CurrentFrame[i][j]-RefFrame[i][j])*(CurrentFrame[i][j]-RefFrame[i][j]);
}
mse=msesum/(288*352);
psnr=10*log10(255*255/mse);
MSESUM+=msesum;
fseek(ReconImage,sizeof(unsigned char)*352*288/2,1);
fwrite(PRefFrame,sizeof(unsigned char),288*352,ReconImage);
cout<<"第"<<frameNO<<"帧"<<psnr<<";"<<"平均搜索点数:"<<kAverage<<endl;
}
fclose(Yuv_file);
fclose(ReconImage);
PSNR=10*log10(255*255/(MSESUM/(288*352*(frameNOMax-1))));
KAVERAGE=(float)KSUM/(396*(frameNOMax-1));
cout<<"平均PSNR:"<<PSNR<<";"<<"平均搜索点数:"<<KAVERAGE<<endl;
cout<<clock()<<endl;
}
void frame_ME(int y0,int x0) //估计函数
{
int N=0; //记录每块的搜索点数
int imin=65535,jmin=65535;
unsigned int BSadMin=65535;
unsigned int BSad=65535;
BSadMin=65535;
FullSearch(y0,x0,imin,jmin,BSadMin,N);
BSad=BSadMin;
CurMV->xoff=jmin,CurMV->yoff=imin;
kSum+=N;
}
void FullSearch(int i,int j,int& imin,int& jmin,unsigned int& BSadMin,int& N)
{
int m,n,dx;
unsigned int BSad=65535;
unsigned int BSad0=65535;
BSad0=SadFun(i,j,i,j); //原点位置
N+=1;
if(BSad0<=T)
{imin=0,jmin=0;
return;
}
for(dx=1;dx<16;dx++)
{
for(int k=1;k<=4;k++) //分四条边搜索
{
switch(k)
{case 1:m=dx,n=dx;
for(n=dx;n>-dx;n--)
{
if(i+m<0||i+m>yMax||j+n<0||j+n>xMax) //图像边界
{;}//边界条件
else
{
BSad=SadFun(m+i,n+j,i,j);
N+=1;
if(BSad<BSadMin)//当前点sad值小于最小值则保存此当前点状态,值与坐标
{
BSadMin=BSad,imin=m,jmin=n;
}
if(BSadMin<=T)
return;
}
}
break;
case 2: m=dx,n=-dx;
for(m=dx;m>-dx;m--)
{
if(i+m<0||i+m>yMax||j+n<0||j+n>xMax) //图像边界
{;}//边界条件
else
{
BSad=SadFun(m+i,n+j,i,j);
N+=1;
if(BSad<BSadMin)//当前点sad值小于最小值则保存此当前点状态,值与坐标
{
BSadMin=BSad,imin=m,jmin=n;
}
if(BSadMin<=T)
return;
}
}
break;
case 3: m=-dx,n=-dx;
for(n=-dx;n<dx;n++)
{
if(i+m<0||i+m>yMax||j+n<0||j+n>xMax) //图像边界
{;}//边界条件
else
{
BSad=SadFun(m+i,n+j,i,j);
N+=1;
if(BSad<BSadMin)//当前点sad值小于最小值则保存此当前点状态,值与坐标
{
BSadMin=BSad,imin=m,jmin=n;
}
if(BSadMin<=T)
return;
}
}
break;
case 4:m=-dx,n=dx;
for(m=-dx;m<dx;m++)
{
if(i+m<0||i+m>yMax||j+n<0||j+n>xMax) //图像边界
{;}//边界条件
else
{
BSad=SadFun(m+i,n+j,i,j);
N+=1;
if(BSad<BSadMin)//当前点sad值小于最小值则保存此当前点状态,值与坐标
{
BSadMin=BSad,imin=m,jmin=n;
}
if(BSadMin<=T)
return;
}
}
break;
}
}
}
if(BSad0<BSadMin)
{BSadMin=BSad0,imin=0,jmin=0;}
}
//求sad值
unsigned int SadFun(int ycur,int xcur,int y0,int x0)
{
unsigned int sum=0;
for(int i=0;i<16;i++)
for(int j=0;j<16;j++)
sum+=abs(CurrentFrame[y0+i][x0+j]-RefOrgFrame[ycur+i][xcur+j]);
return sum;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -