人脸识别、人脸比较、图像转换

// peizhi.cpp : Defines the entry point for the console application.

//

#include "stdafx.h"

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "cv.h"

#include "highgui.h"

#include "cvcam.h"

#include "cxcore.h"

static CvMemStorage* storage=0;

static CvHaarClassifierCascade* cascade = 0;

void detect_and_draw( IplImage* image );

void cam_move(double length,double f);

void change_focus(double length,double f);

IplImage *CvRectToImage(IplImage *img);//根据已知的矩形获取图像

IplImage *ThreeToOne(IplImage *img); //将三通道彩色图像转换成单通道灰度图像

IplImage *GetExampleImage(char *filename);//获得用于对比的目标图像的函数

int JudgeResult();

void compare_picture(IplImage *example,IplImage *object);

static double Width=0,Height=0;//表示摄像头获得图像的大小

IplImage *face=0;//用于指向检测到的人脸

#define MAX1 0.5

#define MIN1 0.2

#define SIZE 0.3//人脸占整个图片的比例调节在0.2-0.5的范围外时(以高度计算),统一修改成比例0.3,

const char *cascade_name ="C://Program Files//OpenCV//data//haarcascades//haarcascade_frontalface_alt2.xml";

CvRect info=cvRect(50,50,50,50); //包含了检测到的图像的坐标信息

int _tmain(int argc, _TCHAR* argv[])

{

storage = cvCreateMemStorage(0);

char filename[20]="01.bmp";

IplImage *img=GetExampleImage(filename);//目标图像

cvNamedWindow("ex",1);

if(!img)

{

printf("出错/n");

exit(0);

}

cvShowImage("ex",img);

CvCapture* capture =cvCaptureFromCAM(0);

IplImage *frame, *frame_copy = 0;

cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );

if( !cascade )

{

printf("无法找到文件/n");

return -1;

}

else

printf("找到了相应的文件/n");

cvNamedWindow( "result", 1 );

cvNamedWindow("face",1);

for(;;)

{

if(!cvGrabFrame(capture))

{

printf("无法打开摄像头/n");

break;

}

frame = cvRetrieveFrame( capture );

Width=(double)frame->width;

Height=(double)frame->height;

if(!frame )

break;

if( !frame_copy )

frame_copy = cvCreateImage( cvSize(frame->width,frame->height),

IPL_DEPTH_8U, frame->nChannels );

if( frame->origin == IPL_ORIGIN_TL )

cvCopy( frame, frame_copy, 0 );

else

cvFlip( frame, frame_copy, 0 );

detect_and_draw( frame_copy );

face=CvRectToImage(frame);

//cvResize(face,img,2);

cvShowImage("face",face);

compare_picture(img,face);

if(JudgeResult()==1)

printf("识别成功/n");

//change_focus(2,0.0036);

// cam_move(2.0,0.0036);

//printf("%d",info->x);

cvWaitKey(100);

}

cvReleaseImage( &frame_copy );

cvReleaseImage(&face);

cvReleaseCapture( &capture );

cvWaitKey(0);

cvDestroyWindow("result");

cvDestroyWindow("face");

cvDestroyWindow("ex");

return 0;

}

void detect_and_draw( IplImage* img )

{

static CvScalar colors[] =

{

{{0,0,255}},

{{0,128,255}},

{{0,255,255}},

{{0,255,0}},

{{255,128,0}},

{{255,255,0}},

{{255,0,0}},

{{255,0,255}}

};

double scale = 1.3;

IplImage* gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );

IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),cvRound (img->height/scale)),8, 1 );

int i;

cvCvtColor( img, gray, CV_BGR2GRAY );

cvResize( gray, small_img, CV_INTER_LINEAR );

cvEqualizeHist( small_img, small_img );

cvClearMemStorage( storage );

if( cascade )

{

//double t = (double)cvGetTickCount();

CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,1.1, 2, 0,cvSize(30, 30) );

for( i = 0; i < (faces ? faces->total : 0); i++ )

{

CvRect* r = (CvRect*)cvGetSeqElem( faces, i );

info = *r;

CvPoint center;

int radius;

center.x = cvRound((r->x + r->width*0.5)*scale);

center.y = cvRound((r->y + r->height*0.5)*scale);

radius = cvRound((r->width + r->height)*0.25*scale);

cvCircle( img, center, radius, colors[i%8], 3, 8, 0 );

}

}

cvShowImage( "result", img );

cvReleaseImage( &gray );

cvReleaseImage( &small_img );

}

void cam_move(double length,double f)//length表示摄像机到人脸的距离,f是焦距,以米为单位,控制摄像头的移动

{

double center_h=Height/2;

double center_w=Width/2;//图片中心的坐标

double face_w=((double)info.x+(double)info.x+(double)info.width)/2;

double face_h=((double)info.y+(double)info.y+(double)info.height)/2;//检测到的人脸中心坐标

/*摄像头的ccd规格尺寸是 4.8mm 3.6mm,利用公式W/w=length/f进行计算*/

double move_x=(length/f)*(0.0048)*((face_w-center_w)/Width);//实际物体的偏移量

double move_y=(length/f)*(0.0036)*((face_h-center_h)/Height);//实际物体的偏移量

double angle_x=0,angle_y=0;

if(move_x>=0) //右偏

{

angle_x=atan(move_x/length)*180/3.14159;//使用反三角函数求角度

//右移angle_x

}

else

{

angle_x=atan(move_x*(-1)/length)*180/3.14159;

//左偏转角度angle_x)

}

if(move_y>=0)

{

angle_y=atan(move_y/length)*180/3.14159;

//下移转角angle_y

}

else

{

angle_y=atan(move_y*(-1)/length)*180/3.14159;

//上移angle_y

}

// printf("移动的角度%lf/t%lf/n",angle_x,angle_y);

}

void change_focus(double length,double f)//调焦函数

{

if(info.height/Height>=MIN1&&info.height/Height<=MAX1)

return; //不需要调节

double pre_w=(length/f)*0.0048;//调焦前的图片对应的实际宽度

double pre_h=(length/f)*0.0036;//实际高度

double times=(info.height/Height)/SIZE;//实际比例与所需调节比例的倍数关系

f=f/times;//修改焦距

//控制摄像头修改焦距

//printf("焦距是:%lf/n",f);

}

IplImage *ThreeToOne(IplImage *img)//多通道与单通道转换

{

IplImage *dst=cvCreateImage(cvGetSize(img),img->depth,1);

cvCvtColor(img,dst,CV_BGR2GRAY);

return dst;

}

int HistogramBins = 256;

float HistogramRange1[2]={0,255};

float *HistogramRange[1]={&HistogramRange1[0]};

double compare_result[2]={0};//用于存储两个图像的比较结果

/*注意,该函数比较的必须是单通道灰度图像,否则需要转换*/

void compare_picture(IplImage *example,IplImage *object)//比较两个图像的相似度

{

example=ThreeToOne(example);

object=ThreeToOne(object);

//cvResize(example,object);

CvHistogram *Histogram1=cvCreateHist(1,&HistogramBins,CV_HIST_SPARSE,HistogramRange);//创建直方图

CvHistogram *Histogram2=cvCreateHist(1,&HistogramBins,CV_HIST_SPARSE,HistogramRange);

cvCalcHist(&example,Histogram1);//计算图像的直方图

cvCalcHist(&object,Histogram2);

cvNormalizeHist(Histogram1,1);//归一化直方图

cvNormalizeHist(Histogram2,1);

double chisqr=cvCompareHist(Histogram1,Histogram2,CV_COMP_CHISQR);//卡方

double bha=cvCompareHist(Histogram1,Histogram2,CV_COMP_BHATTACHARYYA);//Bhattacharyya

compare_result[0]=chisqr;//存储卡方,卡方越小越相似

compare_result[1]=bha;//存储Bhattacharyya,越小越相似

}

#define CHISQR 0.25 //当chisqr<=0.15时判断为相同

#define BHA 0.25 //当bha<=0.15时判断相同

int JudgeResult()//根据比较结果判断是否相同

{

//printf("%f/t%f/n",compare_result[0],compare_result[1]);

if(compare_result[0]<=CHISQR&&compare_result[1]<=BHA)

return 1; //表示两张图片结果相同

else

return 0; //表示两张图片结果不相同

}

#define SCALE 1.2

IplImage *CvRectToImage(IplImage *img)//通过原图像和所得矩阵,获得检测到人脸的图像

{

CvRect info_copy=info;

info_copy.width*=SCALE;

info_copy.height*=SCALE;

info_copy.x*=SCALE;

info_copy.y*=SCALE;

cvSetImageROI(img, info_copy);

IplImage *smallface=cvCreateImage( cvSize(info_copy.width,info_copy.height), 8, 3 );

cvCopy(img,smallface);

cvResetImageROI(img);

cvConvertImage(smallface,smallface,CV_CVTIMG_FLIP );

return smallface;

}

IplImage *GetExampleImage(char *filename)

{

IplImage *img=cvLoadImage(filename,-1);

double scale =SCALE;

IplImage* gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );

IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),cvRound (img->height/scale)),8, 1 );

cvCvtColor( img, gray, CV_BGR2GRAY );

cvResize(gray, small_img, CV_INTER_LINEAR );

cvEqualizeHist( small_img, small_img );

cvClearMemStorage( storage );

cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );

if( cascade )

{

CvRect* r=0;

CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,1.1, 2, 0,cvSize(30, 30) );

for(int i = 0; i < (faces ? faces->total : 0); i++ )

r = (CvRect*)cvGetSeqElem( faces, i);

if(r==0)

return 0;

r->width*=SCALE;

r->height*=SCALE;

r->x*=SCALE;

r->y*=SCALE;

cvSetImageROI(img, *r);

IplImage *smallface=cvCreateImage( cvSize(r->width,r->height), 8, 3 );

cvCopy(img,smallface);

cvResetImageROI(img);

return smallface;

}

else

return 0;

}

你可能感兴趣的:(人脸识别、人脸比较、图像转换)