基于正玄变换的人脸姿态矫正(由正面人脸图像模拟出侧面人脸图像)

基于正玄变换的人脸姿态矫正

原理:正玄变换开始是用于快速的姿态矫正,即从有一定偏转角度的侧面图像变为正面图像。假设待识别的样本为的一张侧面人脸图像,即此人脸具有一定方向的偏转。可以看到图像显示出一边被压缩,另一边被放大的效果。而一张正面人脸则是两边对称的。所以以人脸的中心垂线为界,左边的列坐标取负,右边的列坐标取正,这样根据列坐标的正负不同施行不同的尺度变换,就可以压缩一边的同时扩展另一边,从而变换为正面人脸原始列坐标都是整数变换后不再是整数,此时可以进行插值运算,可求出对应像素点的灰度值。

设样本为S,大小为,平面上网格点为,经过正弦变换后,网格点上新的y值为:

 

根据上面的式子对图像进行变换,由组成图像上新的网格点。假设新图像在网格点处的灰度值为原图像在(x,y)点的值,由作插值求出图像在网格点上的值。

效果图:

 

原图像

 

                

原图              左侧旋转10度   左侧旋转15度   左侧旋转20

               

原图            右侧旋转10度  右侧旋转15度    右侧旋转20

 

程序:

/*

write by fangqi su 2014-8-15

*/

#include

using namespace cv;

int main()

{

Mat srcpixel=imread("E:\\海信项目资料\\最全人脸库\\FERET_80_80-人脸数据库\\FERET-002\\01.tif",0);

int width=srcpixel.cols;

int height=srcpixel.rows;

double alfa=-20*CV_PI/180;

double fy=1;

int outWidth=(int)max(((1+sin(alfa))*width-sin(alfa)*(width/2)),((1-sin(alfa))*width+sin(alfa)*(width/2)));

int outHeight=height;

Mat objPixel(outHeight,outWidth,srcpixel.type());

namedWindow("ss");

namedWindow("ss1");

double x=0.0;//变换后的像素坐标

double y=0.0;//变换后的像素纵坐标

double deta=0.85;

for(int j=0;j

{

y=j/fy;

for(int i=0;i

{

if(x>width/2)

{

x=deta*(i+sin(alfa)*(outWidth/2))/(1+sin(alfa));

if(x<0)

continue;

}

else

{

x=deta*(i-sin(alfa)*(outWidth/2))/(1-sin(alfa));

if(x<0)

continue;

}

Point LeftTop,RightBottom,LeftBottom,RightTop;

LeftTop.x=(int)x;

LeftTop.y=(int)y;

if(LeftTop.x>width)

{

continue;

//LeftTop.x=width-1;

}

RightTop.x=LeftTop.x+1;

RightTop.y=LeftTop.y;

if(RightTop.x>width)

{

continue;

//RightTop.x=width-1;

}

LeftBottom.x=LeftTop.x;

LeftBottom.y=LeftTop.y+1;

RightBottom.x=LeftTop.x+1;

RightBottom.y=LeftTop.y+1;

if(RightBottom.x>width)

{

continue;

//RightBottom.x=width-1;

}

uchar clr1,clr2,clr3,clr4;

double u,v;

u=x-(int)x;

v=y-(int)y;

//如果坐标在图像的右下角

if((x>=width-1)&&(y>=width-1))

{

clr1=srcpixel.at<uchar>(LeftTop.x,LeftTop.y);

objPixel.at<uchar>(j,i)=clr1;

}

//如果坐标在最后一列的外侧

else if((x>=width-1))

{

clr1=srcpixel.at<uchar>(LeftTop.x,LeftTop.y);

clr3=srcpixel.at<uchar>(LeftBottom.x,LeftBottom.y);

objPixel.at<uchar>(j,i)=(uchar)(clr1*(1-v)+clr3*v);

 

}

//如果图像在最后一行外侧

else if(y>=height-1)

{

clr1=srcpixel.at<uchar>(LeftTop.x,LeftTop.y);

clr2=srcpixel.at<uchar>(RightTop.x,RightTop.y);

objPixel.at<uchar>(j,i)=(uchar)(clr1*(1-u)+clr2*u);

}

else

{

clr1=srcpixel.at<uchar>(LeftTop);

clr2=srcpixel.at<uchar>(RightTop);

clr3=srcpixel.at<uchar>(LeftBottom);

clr4=srcpixel.at<uchar>(RightBottom);

double f1,f2;

f1=clr1*(1-u)+clr2*u;

f2=clr3*(1-u)+clr4*u;

objPixel.at<uchar>(j,i)=(uchar)(f1*(1-v)+f2*v);

}

 

 

}

}

imshow("ss",objPixel);

imshow("ss1",srcpixel);

cvWaitKey(0);

}

 

你可能感兴趣的:(基于正玄变换的人脸姿态矫正(由正面人脸图像模拟出侧面人脸图像))