基于Opencv的人脸检测及识别

一、实验目的:我这里完成的是,将8张人脸图片(4组,每组两张)存入库中,选取1张图片,程序识别出与其匹配的另一张。

这里介绍分三个步骤完成该工作,①程序读取摄像头、拍照

               ②程序从电脑文档中读取图片

                 ③检测人脸,并用红框框出人脸

④使用感知哈希算法匹配最相似的图片

二、实验环境: Win 7(x64)、visual studio 2010、openCV-2.4.3

使用语言:C++

三、实验准备:①安装好vs2010,本文不予介绍。

       ②配置opencv :

  1‘进入官网下载http://opencv.org/  (OpenCv 2.4x是支持Vs2010的,建议根据自己的Vs版本安装相应的OpenCv的版本)解压后,目录如下:

  2‘打开vs2010,创建项目,这里以我的工程名test为例。右击项目->属性->vc++目录->包含目录, 添加三个路径:(在解压后opencv下的build目录)

E:\新建文件夹\opencv\build\include

E:\新建文件夹\opencv\build\include\opencv

E:\新建文件夹\opencv\build\include\opencv2

然后点击库目录,添加路径:E:\新建文件夹\opencv\build\x86\vc10\lib

配置好了后,第二步,点击链接器->输入->附加依赖项,编辑添加,把E:\新建文件夹\opencv\build\x86\vc10\bin里面左右的文件名称全导入进去,导入带d的文件,比如有opencv_calib3d243.dll与opencv_calib3d243d.dll文件,只需添加后者带d的即可。

至此,openCV配置已经全部完成。接下来编写代码。

四、编写代码

①为了收集图片库,我编写了直接拍照的功能,按下p进行拍照,并自动命名排序存到文件中。

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main( int argc, char** argv )
{

    int i=1;//照片名从1开始命名
    while(1)
    {
    CvCapture *pCapture=cvCreateCameraCapture(-1);//打开摄像头
    Mat image=cvQueryFrame(pCapture); //将摄像头拍的以图片形式展现
    cvNamedWindow("frame",1);  //命名一个窗口
    imshow("frame",image);       //在窗口显示图片
    string filename=format("C:\\images\\%d.jpg",i);
    char key=waitKey(100);
    switch(key)
    {
    case‘p‘:
        i++;                                    //键盘上每按一次p,就拍一张照
        imwrite(filename,image);              //写入图片
        imshow("photo",image);               //展示照片
        waitKey(500);
        destroyWindow("photo");
        break;
        default:break;
        }
        }
}

实验效果:

②读取图片,显示在屏幕上

    Mat image=imread("C:\\images\\2.jpg",-1);    //使用Mat创建一个对象,-1为打开类型的参数
    cvNamedWindow("图像显示",1);                        //命名一个窗口 ,1为显示参数
    imshow("图像显示",image);
    cvWaitKey(0);  //很重要,不写读不出来

③将读取的图片进行检测出人脸。

首先找到opencv目录下,识别人脸的类的文件(包装在data路径下)

Haarcascades_frontalface_default 包装的是 检测人脸,将这个文件拷贝到你的vs工程下。

#include <iostream>
#include <string>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/gpu/gpu.hpp>
using namespace cv;
using namespace std;
string xmlPath="C:\\Users\\yu\\Documents\\Visual Studio 2010\\Projects\\加我南\\haarcascade_frontalface_default.xml";
//xmlpath 字符串记录那个.xml文件的路径
void detectAndDisplay(Mat image);
int main( int argc,char**argv )
{
    string path="C:\\Users\\yu\\Documents\\Visual Studio 2010\\Projects\\test\\images\\1.jpg";//以检测图片1.jpg为例
    Mat image =imread(path,-1);

    CascadeClassifier a;     //创建脸部对象
    if(!a.load(xmlPath))     //如果读取文件不出错,则检测人脸
    {
        cout<<"无法加载xml文件"<<endl;
        return 0;
    }
   detectAndDisplay(image);// 检测人脸
   return 0;

}

void detectAndDisplay(Mat image)
{
    CascadeClassifier ccf;      //创建脸部对象
    ccf.load(xmlPath);           //导入opencv自带检测的文件
    vector<Rect> faces;
    Mat gray;
    cvtColor(image,gray,CV_BGR2GRAY);
    equalizeHist(gray,gray);
    ccf.detectMultiScale(gray,faces,1.1,3,0,Size(50,50),Size(500,500));
    for(vector<Rect>::const_iterator iter=faces.begin();iter!=faces.end();iter++)
    {
        rectangle(image,*iter,Scalar(0,0,255),2,8); //画出脸部矩形
    }
    Mat image1;

    for(size_t i=0;i<faces.size();i++)
    {
        Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
        image1= image(Rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height));
    }

    imshow("1",image);
    imshow("2",image1);
    cvWaitKey(0);

}

实验结果如下:

④进行人脸检测

opencv的FaceRecogizer目前有三个类实现了它,特征脸和fisherface方法最少训练图像为两张,而LBP可以单张图像训练,LBP方法原理:

引用:http://blog.csdn.net/lsq2902101015/article/details/49717441

因此,我想到了与LBP算法类似的感知哈希算法。

说下原理过程:

(1)缩小尺寸:去除高频和细节的最快方法是缩小图片,将图片缩小到8x8的尺寸,共64个像素。不用保持纵横比,只需将其变成8x8的正方形,这样就可以摒弃不同尺寸、比例带来的图片差异
      (2)简化色彩:将8x8的小图片转换成灰度图像。
      (3)计算平均值:计算所有64个像素的灰度平均值
      (4)比较像素的灰度:将每个像素的灰度,与平均值进行比较,大于或等于就记为1,小于均值,就记为0;
       (5)计算hash值,将上面的比价比较结果组合在一起,构成了64位的哈希值,就是这张图片的指纹。
       (6)通过比较两张图片的哈希值,计算差值得到汉明距离。汉明距离越小,说明两张图片越相似。
  引用:http://blog.csdn.net/zouxy09/article/details/17471401

#include <iostream>
#include <string>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/gpu/gpu.hpp>
using namespace cv;
string xmlPath="C:\\Users\\yu\\Documents\\Visual Studio 2010\\Projects\\加我南\\haarcascade_frontalface_default.xml";

string HashValue(Mat &src)      //得到图片的哈希值
//很久之前写的,现在想不起来了...注释就先不写了.....抱歉哈。但是是可以运行的
{
    string rst(64,‘\0‘);
    Mat img;
    if(src.channels()==3)
        cvtColor(src,img,CV_BGR2GRAY);
    else
        img=src.clone();
    resize(img,img,Size(8,8));
    uchar *pData;
    for(int i=0;i<img.rows;i++)
    {
        pData=img.ptr<uchar>(i);
        for(int j=0;j<img.cols;j++)
        {
            pData[j]=pData[j]/4;
        }
    }

    int average=mean(img).val[0];
    Mat mask=(img>=(uchar)average);
    int index=0;
    for(int i=0;i<mask.rows;i++)
    {
        pData = mask.ptr<uchar>(i);
        for(int j=0;j<mask.cols;j++)
        {
            if(pData[j]==0)
                rst[index++]=‘0‘;
            else
                rst[index++]=‘1‘;
        }
    }
    return rst;
}
int HanmingDistance(string &str1,string &str2)       //求两张图片的汉明距离
{
    if((str1.size()!=64)||(str2.size()!=64))
        return -1;
    int diff=0;
    for(int i=0;i<64;i++)
    {
        if(str1[i]!=str2[i])
            diff++;
    }
    return diff;
}
void detectAndDisplay(Mat image)
{
    CascadeClassifier ccf;
    ccf.load(xmlPath);
    vector<Rect> faces;
    Mat gray;
    cvtColor(image,gray,CV_BGR2GRAY);
    equalizeHist(gray,gray);
    ccf.detectMultiScale(gray,faces,1.1,3,0,Size(50,50),Size(500,500));
    for(vector<Rect>::const_iterator iter=faces.begin();iter!=faces.end();iter++)
    {
        rectangle(image,*iter,Scalar(0,0,255),2,8); //画出脸部矩形
    }
    for(size_t i=0;i<faces.size();i++)
    {
        Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
        image= image(Rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height));
    }
}             //识别并截取人脸
int main( int argc, char** argv )
{
    using std::cout;
    using std::endl;
    using std::cin;
    cout<<"请输入想要选择的图片"<<endl;
    int a,x,i;
    int diff[9];
    cin>>a;
    const string path1=format("C:\\Users\\yu\\Documents\\Visual Studio 2010\\Projects\\test\\images\\%d.jpg",a);
    Mat image1,image2;
    image1=imread(path1,-1);
    string str1,str2,path2;
    cvNamedWindow("选择的图片",1);
    /*cvResizeWindow("选择的图片",700,500);*/
    imshow("选择的图片",image1);
    detectAndDisplay(image1);
    str1=HashValue(image1);
    cvWaitKey(0);
    for(i=1;i<=8;i++)//因为我完成的就是8张图片的检测,所以循环值为8
    {
        path2=format("C:\\Users\\yu\\Documents\\Visual Studio 2010\\Projects\\test\\images\\%d.jpg",i);
        image2=imread(path2,-1);
        detectAndDisplay(image2);
        str2=HashValue(image2);
        diff[i]=HanmingDistance(str1,str2);
    }

    int min=1000,t;
    for(i=1;i<=8;i++)    //循环值为8,求与原图片汉明距离最小的那张图片
    {
        if(min>diff[i]&&diff[i]!=0)
            {
                min=diff[i];
                t=i;}           //检测出的标记为t
    }
    path2=format("C:\\Users\\yu\\Documents\\Visual Studio 2010\\Projects\\test\\images\\%d.jpg",t);
    image2=imread(path2,-1);//将图片t显示出来
    cvNamedWindow("相似的图片",1);
    imshow("相似的图片",image2);//这时显示的就是最相似的照片
    cvWaitKey(0);
    cin.get();                    //吃掉回车符
}

实验结果如下:

我的照片库如下:

至此,简单地完成了检测并且识别人脸的功能。

时间: 2024-08-12 20:57:20

基于Opencv的人脸检测及识别的相关文章

基于OpenCv的人脸检测、识别系统学习制作笔记之三

1.在windows下编写人脸检测.识别系统.目前已完成:可利用摄像头提取图像,并将人脸检测出来,未进行识别. 2.在linux下进行编译在windows环境下已经能运行的代码. 为此进行了linux系统下OpenCv的安装. 在linux中安装OpenCv遇到了很多问题,已经解决,但是花费了不少时间.目前:可以在linux下编译OpenCv项目,但是运行生成的程序时出现问题.初步认定为采用了虚拟机而导致运行内存不足,程序直接崩溃,将继续解决这个问题. 花费较多时间安装OpenCv是有必要的,为

基于OpenCv的人脸检测、识别系统学习制作笔记之一

基于OpenCv从视频到摄像头的人脸检测 在OpenCv中读取视频文件和读取摄像头的的视频流然后在放在一个窗口中显示结果其实是类似的一个实现过程. 先创建一个指向CvCapture结构的指针 CvCapture *capture; 再用两个函数就可以分别获取到视频文件或者摄像头的一些状态信息,然后把这些信息放进去之前指向的结构体 视频文件 capture = cvCreateCameraCapture(0); 打开摄像头 capture = cvCreateFileCapture(argv[1]

基于opencv的人脸检测的web应用

参考资料 https://github.com/bsdnoobz/web-based-face-detect http://opencv-code.com/projects/web-based-interface-for-face-detection-with-opencv/ http://www.cnblogs.com/findingsea/archive/2012/03/31/2427833.html 流程如下图 背景知识 php调用exe的返回 <html> <body> &

qml+opencv(三)人脸检测与识别

ccface 介绍 这个我闲的蛋疼无聊做的一个人脸检测和识别的小程序. 环境 Qt5+opencv2.4.9 使用 通过File菜单打开关闭摄像头 ID填入标识,save保存 select 识别 检测 save 识别 程序地址: https://git.oschina.net/zhouX/ccface.git

基于openCV实现人脸检测

openCV的人脸识别主要通过Haar分类器实现,当然,这是在已有训练数据的基础上.openCV安装在 opencv/opencv/sources/data/haarcascades_cuda(或haarcascades)中存在预先训练好的物体检测器(xml格式),包括正脸.侧脸.眼睛.微笑.上半身.下半身.全身等. openCV的的Haar分类器是一个监督分类器,首先对图像进行直方图均衡化并归一化到同样大小,然后标记里面是否包含要监测的物体.它首先由Paul Viola和Michael Jon

人工智能之基于face_recognition的人脸检测与识别

不久乘高铁出行,看见高铁火车站已经实现了"刷脸进站",而且效率很高,很感兴趣,今天抽时间研究一下,其实没那么复杂. 我基本上是基于https://github.com/ageitgey/face_recognition上的资料和源码做一些尝试和试验. 首先,需要配置我们的python环境,我悬着的python27(比较稳定),具体过程不多说了. 然后,需要安装这次的主角face_recognition库,这个的安装花了我不少时间,需要注意一下几点(按照本人的环境): 1,首先,安装vi

基于 OpenCV 的人脸识别

基于 OpenCV 的人脸识别 一点背景知识 OpenCV 是一个开源的计算机视觉和机器学习库.它包含成千上万优化过的算法,为各种计算机视觉应用提供了一个通用工具包.根据这个项目的关于页面,OpenCV 已被广泛运用在各种项目上,从谷歌街景的图片拼接,到交互艺术展览的技术实现中,都有 OpenCV 的身影. OpenCV 起始于 1999 年 Intel 的一个内部研究项目.从那时起,它的开发就一直很活跃.进化到现在,它已支持如 OpenCL 和 OpenGL 的多种现代技术,也支持如 iOS

C++开发人脸性别识别教程(4)——OpenCv的人脸检测函数

这个项目主要包含三部分:人脸检测.特征提取.性别分类: 这篇博客中我们重点介绍OpenCv的人脸检测函数.这篇博客我们先不提MFC,而是在win32控制台下编写一段人脸检测的程序. 一.开启摄像头 我们先讲解如何通过摄像头来采集图像,这听起来更有实际意义. 1.新建工程并配置OpenCv(注意工程类型选择win32控制台应用程序): 2.包含头文件 OpenCv2.x版本包含头文件非常方便,一句话搞定: #include <opencv2\opencv.hpp> using namespace

OpenCV&amp;Qt学习之四——OpenCV 实现人脸检测与相关知识整理

开发配置 OpenCV的例程中已经带有了人脸检测的例程,位置在:OpenCV\samples\facedetect.cpp文件,OpenCV的安装与这个例子的测试可以参考我之前的博文Linux 下编译安装OpenCV. 网上能够找到关于OpenCV人脸检测的例子也比较多,大多也都是基于这个例程来更改,只是多数使用的是OpenCV 1.0的版本,而OpenCV2.0以后由于模块结构的更改,很多人并没有将例程运行起来.如果是新版的OpenCV跑旧的例程,编译运行出错的话,需要确保: #include