• OpenCV入门指南----人脸检测


    本篇介绍图像处理与模式识别中最热门的一个领域——人脸检测(人脸识别)。人脸检测可以说是学术界的宠儿,在不少EI,SCI高级别论文都能看到它的身影。甚至很多高校学生的毕业设计都会涉及到人脸检测。当然人脸检测的巨大实用价值也让很多公司纷纷关注,很多公司都拥有这方面的专利或是开发商业产品出售。

        在OpenCV中,人脸检测也是其热门应用之一。在OpenCV的特征检测专题就详细介绍了人脸检测的原理——通过Haar特征来识别是否为人脸。Haar特征检测原理与Haar特征分类器的训练放到下一篇《【OpenCV入门指南】第十四篇  Haartraining》来讲,本篇主要介绍如何在OpenCV中使用Haar特征分类器来对图像中的人脸进行检测和识别。下面将分成五步来详细示范如何在OpenCV中进行人脸识别:

        一.人脸的Haar特征分类器是什么

        二.在哪找人脸的Haar特征分类器

        三.怎么用人脸的Haar特征分类器

        四.人脸识别示例代码

        五.人脸识别程序运行结果

    一.人脸的Haar特征分类器是什么

    人脸的Haar特征分类器就是一个XML文件,该文件中会描述人脸的Haar特征值。当然Haar特征的用途可不止可以用来描述人脸这一种,用来描述眼睛,嘴唇或是其它物体也是可以的。

    二.在哪找人脸的Haar特征分类器

    OpenCV有已经自带了人脸的Haar特征分类器。OpenCV安装目录中的data haarcascades目录下的haarcascade_frontalface_alt.xml与haarcascade_frontalface_alt2.xml都是用来检测人脸的Haar分类器。这个haarcascades目录下还有人的全身,眼睛,嘴唇的Haar分类器。读者可以仿照本方的例子来试验下效果看看。

    三.怎么用人脸的Haar特征分类器

    使用人脸的Haar特征分类器非常之简单,直接使用cvHaarDetectObjects。下面来看看这个函数的介绍:

    函数功能:检测图像中的目录

    函数原型:

    CVAPI(CvSeq*) cvHaarDetectObjects(

      const CvArr* image,

      CvHaarClassifierCascade* cascade,

      CvMemStorage* storage,

      double scale_factor CV_DEFAULT(1.1),

      int min_neighbors CV_DEFAULT(3),

      int flags CV_DEFAULT(0),

      CvSize min_size CV_DEFAULT(cvSize(0,0)),

      CvSize max_size CV_DEFAULT(cvSize(0,0))

    );

    函数说明:

    第一个参数表示输入图像,尽量使用灰度图以加快检测速度。

    第二个参数表示Haar特征分类器,可以用cvLoad()函数来从磁盘中加载xml文件作为Haar特征分类器。

    第三个参数为CvMemStorage类型,大家应该很熟悉这个CvMemStorage类型了,《OpenCV入门指南》中很多文章都介绍过了。

    第四个参数表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%

    第五个参数表示构成检测目标的相邻矩形的最小个数(默认为3个)。如果组成检测目标的小矩形的个数和小于 min_neighbors - 1 都会被排除。如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框,这种设定值一般用在用户自定义对检测结果的组合程序上。

    第六个参数要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测来排除边缘过多或过少的区域,因此这些区域通常不会是人脸所在区域。

    第七个,第八个参数表示检测窗口的最小值和最大值,一般设置为默认即可。

    函数返回值:

    函数将返回CvSeq对象,该对象包含一系列CvRect表示检测到的人脸矩形。

    四.人脸识别示例代码

    下面给出一个完整的示例代码,代码中的GetTickCount可以参阅《Windows 各种计时函数总结》,cvEqualizeHist可以参阅《【OpenCV入门指南】第八篇灰度直方图》。

    // FaceDetect.cpp : 定义控制台应用程序的入口点。
    // 本文配套博客文章地址: http://blog.csdn.net/morewindows/article/details/8426318  
    
    #include "stdafx.h"
    
    #include <iostream>
    #include <opencv2/core/core.hpp>   //cvGetSize  cvCreateImage
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/opencv.hpp>  //cvResize cvInitMatHeader cvGetMinMaxHistValue cvCvtColor
    #include <opencv2/imgproc/imgproc.hpp>
    
    #include <Windows.h>   //DWORD  GetTickCount()
    
    #ifdef _DEBUG
    #pragma comment(lib, "opencv_core244d")
    #pragma comment(lib, "opencv_highgui244d")
    #pragma comment(lib, "opencv_imgproc244d")  //cvResize 
    #pragma comment(lib, "opencv_objdetect244d")  //cvHaarDetectObjects
    #else
    #pragma comment(lib, "opencv_core244")
    #pragma comment(lib, "opencv_highgui244")
    #pragma comment(lib, "opencv_imgproc244")  //cvResize
    #pragma comment(lib, "opencv_objdetect244") //cvHaarDetectObjects
    #endif
    
    using namespace std;  
    int main()  
    {  
        // 加载Haar特征检测分类器  
        // haarcascade_frontalface_alt.xml系OpenCV自带的分类器 下面是我机器上的文件路径  
        const char *pstrCascadeFileName = "G:\Software\openCV\opencv\data\haarcascades\haarcascade_frontalface_alt.xml";  
        CvHaarClassifierCascade *pHaarCascade = NULL;  
        pHaarCascade = (CvHaarClassifierCascade*)cvLoad(pstrCascadeFileName);  
      
        // 载入图像  
        const char *pstrImageName = "./images/linzhiling.jpg";  
        //const char *pstrImageName = "./images/liuyifei.jpg";  
        //const char *pstrImageName = "./images/unknown.jpg";  
        IplImage *pSrcImage = cvLoadImage(pstrImageName, CV_LOAD_IMAGE_UNCHANGED);  
          
        IplImage *pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);  
        cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);  
      
        // 人脸识别与标记  
        if (pHaarCascade != NULL)  
        {         
            CvScalar FaceCirclecolors[] =   
            {  
                {{0, 0, 255}},  
                {{0, 128, 255}},  
                {{0, 255, 255}},  
                {{0, 255, 0}},  
                {{255, 128, 0}},  
                {{255, 255, 0}},  
                {{255, 0, 0}},  
                {{255, 0, 255}}  
            };  
      
            CvMemStorage *pcvMStorage = cvCreateMemStorage(0);  
            cvClearMemStorage(pcvMStorage);  
            // 识别  
            DWORD dwTimeBegin, dwTimeEnd;  
            dwTimeBegin = GetTickCount();  
            //函数将返回CvSeq对象,该对象包含一系列CvRect表示检测到的人脸矩形
            //第一个参数表示输入图像,尽量使用灰度图以加快检测速度
            //第二个参数表示Haar特征分类器,可以用cvLoad()函数来从磁盘中加载xml文件作为Haar特征分类器
            //第三个参数为CvMemStorage类型
            //第四个参数表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%
            //第五个参数表示构成检测目标的相邻矩形的最小个数(默认为3个)。如果组成检测目标的小矩形的个数和小于 min_neighbors - 1 都会被排除。
                //如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框,这种设定值一般用在用户自定义对检测结果的组合程序上
            //第六个参数要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测
                //来排除边缘过多或过少的区域,因此这些区域通常不会是人脸所在区域
            //第七个,第八个参数表示检测窗口的最小值和最大值,一般设置为默认即可
            CvSeq *pcvSeqFaces = cvHaarDetectObjects(pGrayImage, pHaarCascade, pcvMStorage);  
            dwTimeEnd = GetTickCount();  
      
            printf("人脸个数: %d   识别用时: %d ms
    ", pcvSeqFaces->total, dwTimeEnd - dwTimeBegin);  
              
            // 标记  
            for(int i = 0; i <pcvSeqFaces->total; i++)  
            {  
                CvRect* r = (CvRect*)cvGetSeqElem(pcvSeqFaces, i);  
    
                //用圆形画出脸部部分
                CvPoint center;  
                int radius;  
                center.x = cvRound((r->x + r->width * 0.5));  
                center.y = cvRound((r->y + r->height * 0.5));  
                radius = cvRound((r->width + r->height) * 0.25);  
                cvCircle(pSrcImage, center, radius, FaceCirclecolors[i % 8], 2); 
                
                //用矩形画出脸部部分
                /*
                CvPoint startPoint,endPoint;
                startPoint.x = cvRound(r->x);
                startPoint.y = cvRound(r->y);
                endPoint.x = cvRound(r->x + r->width);
                endPoint.y = cvRound(r->x + r->height);
                cvRectangle(pSrcImage,startPoint,endPoint,FaceCirclecolors[i % 8]);
                */
            }  
            cvReleaseMemStorage(&pcvMStorage);  
        }  
          
        const char *pstrWindowsTitle = "人脸识别";  
        cvNamedWindow(pstrWindowsTitle, CV_WINDOW_AUTOSIZE);  
        cvShowImage(pstrWindowsTitle, pSrcImage);  
      
        cvWaitKey(0);  
      
        cvDestroyWindow(pstrWindowsTitle);  
        cvReleaseImage(&pSrcImage);   
        cvReleaseImage(&pGrayImage);  
        return 0;  
    }
    View Code

    五.人脸识别程序运行结果

    运行结果一(单人正面):

    这张图的干扰太少,换张干扰大点的图来试试。

    运行结果二:

    运行结果三(多人):

    本文转自:http://blog.csdn.net/morewindows/article/details/8426318

  • 相关阅读:
    JSP动作元素你又知几多?
    一个简单的TCP/IP服务端客户端对话
    使用Graphics2D去除曲线锯齿状
    MySQL数据类型
    Eclipse常用快捷键
    C#中的委托和事件
    GitHub当道,菜鸟也为Git疯狂
    C++文件操作
    JSP指令你知多少?
    spring如何使用多个xml配置文件
  • 原文地址:https://www.cnblogs.com/tianyalu/p/5689285.html
Copyright © 2020-2023  润新知