基于OpenCV的人脸识别考勤系统(二)

该文详细介绍了如何使用OpenCV进行图像处理,包括将图片转换为灰度图和进行直方图均衡化,以提高人脸检测的准确率。接着,文章讲解了如何利用CascadeClassifier进行脸部识别,包括加载训练文件、绘制人脸框和截取人脸图像。代码示例展示了整个流程,从捕获视频到人脸检测,再到人脸图像的编码存储。
摘要由CSDN通过智能技术生成

该部分承接(一),将会实现视频图像的处理以及人脸的识别

目录

四、图像处理

1. cvtColor

2. equalizeHist

五、脸部识别

1. 导入训练文件

2. 绘制人脸框

3. 截取人脸并转换格式


四、图像处理

为了减轻处理器的负担,使得程序运行更加流畅,并提高检测的准确率,我们需要将采集的图片进行灰度处理和均衡化处理。这需要用到两个函数:cvtColor和equalizeHist。这两个函数在官方文档的图像处理部分(imgproc. Image Processing)

1. cvtColor

该函数的官方接口为:

C++: void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 )

Parameters:
  • src – input image: 8-bit unsigned, 16-bit unsigned ( CV_16UC... ), or single-precision floating-point.
  • dst – output image of the same size and depth as src.
  • code – color space conversion code (see the description below).
  • dstCn – number of channels in the destination image; if the parameter is 0, the number of the channels is derived automatically from src and code .

所以我们需要再声明一个Mat类的对象来保存灰度图片,根据官方文档所说,将RGB图片转换成灰度图片可使用CV_RGB2GRAY,因此,代码为:

 

Mat grayImg;
cvtColor(img,grayImg,CV_BGR2GRAY); //灰度处理

2. equalizeHist

该函数的官方接口为:

C++: void equalizeHist(InputArray src, OutputArray dst)

同样,我们需要声明一个Mat类的对象来保存均衡化后的图片,代码为:

Mat equalizeImg;
equalizeHist(grayImg,equalizeImg); //均衡化处理

因此,该部分的完整代码为:

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
    VideoCapture cap(0); // open the default camera
    if(!cap.isOpened())  // check if we succeeded
    {
        cout<<"Camera open failed!"<<endl;
        return -1;
    }
    cout<<"Camera open successfully!"<<endl;

    Mat img;
    Mat grayImg;
    Mat equalizeImg;
    for(;;)
    {
        cap >> img; // get a new img from camera
        cvtColor(img, grayImg, CV_BGR2GRAY); //灰度处理
        equalizeHist(grayImg,equalizeImg); //均衡化处理
        imshow("video", equalizeImg); //在video窗口中展示图片 
        waitKey(40); //设置帧率(40ms读取一帧)
    }

    return 0;
}

值得注意的是,该部分使用了新的库文件,所以编译时需要加上-lopencv_imgproc,即

g++ main.cpp -o main -lopencv_highgui -lopencv_core -lopencv_imgproc

五、脸部识别

1. 导入训练文件

在官方文档的objdetect. Object Detection中,找到CascadeClassifier 。CascadeClassifier是opencv下objdetect模块中用来做目标检测的级联分类器的一个类,它可以帮助我们检测例如车牌、眼睛、人脸等物体。它的大概原理就是判别某个物体是否属于某个分类。以人脸为例,我们可以把眼睛、鼻子、眉毛、嘴巴等属性定义成一个分类器,如果检测到一个模型符合定义人脸的所有属性,那么就认为它是一个人脸。

我们需要实例化该分类器,并使用OpenCV训练好的文件,该文件在/usr/share/opencv/haarcascades/ 目录中,我们选择其中的面部识别的xml文件:haarcascade_frontalface_alt2.xml

相应代码为

CascadeClassifier classifier("/usr/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml");

2. 绘制人脸框

接下来要想实现将人脸检测到,需要借助detectMultiScale函数,该函数的官方接口为:

C++: void CascadeClassifier::detectMultiScale(const Mat& image, vector<Rect>& objects, double scaleFactor=1.1, int minNeighbors=3, int flags=0, Size minSize=Size(), Size maxSize=Size())

根据函数说明,我们需要声明vector<Rect>, 其余参数均有默认值,在此不加以修改,则

Vector<Rect> faces;
classifier.detectMultiScale(equalizeImg, faces); //检测人脸并返回在facas中

接下来需要将得到的人脸框出来,显示在图像上。这需要使用rectangle函数,官方接口为

C++: void rectangle(Mat& img, Rect rec, const Scalar& color, int thickness=1, int lineType=8, int shift=0 )

根据函数说明,我们的代码为:

rectangle(equalizeImg, faces[0], Scalar(255,255,255));

因为1. 导入训练文件中使用了objdetect. Object Detection部分的函数,所以编译命令需要变为:

g++ main.cpp -o main -lopencv_highgui -lopencv_core -lopencv_imgproc -lopencv_objdetect

但是此时会出现一个问题,当运行程序后,一开始摄像头未检测到人脸时,程序会报错。这是因为,当未检测到人脸时,faces里为空,rectangle函数调用faces[0]时出现地址越界错误,因此需要加一个优化。

if(faces.size())
{
    rectangle(equalizeImg, faces[0], Scalar(255,255,255));
}
else
    cout<<"No face detected!"<<endl;

3. 截取人脸并转换格式

在该部分,我们需要将识别到的人脸截取出来,方便上传比对。

我们需要声明一个Mat对象,专门用于存放人脸图像,接下来将绘制出的人脸信息存放进去。

此外,我们需要将图像进行编码,这里需要使用imencode函数,官方接口为:

C++: bool imencode(const string& ext, InputArray img, vector<uchar>& buf, const vector<int>& params=vector<int>())

我们需要指定编码的格式为jpg,新定义一个存放编码后图片的容器vector<uchar>,该部分的代码为:

Mat faceImg;
vector<uchar> jpgBuf;
if(faces.size())
{
    rectangle(equalizeImg, faces[0], Scalar(255,255,255));
    faceImg = equalizeImg(faces[0]);
    imencode(".jpg", faceImg, jpgBuf);
}
else
    cout<<"No face detected!"<<endl;

所以,该部分目前为止的总代码为:

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
    VideoCapture cap(0); // open the default camera
    if(!cap.isOpened())  // check if we succeeded
    {
        cout<<"Camera open failed!"<<endl;
        return -1;
    }
    cout<<"Camera open successfully!"<<endl;

    Mat img;
    Mat grayImg;
    Mat equalizeImg;
    vector<Rect> faces;
    Mat faceImg;
    vector<uchar> jpgBuf;
    
    CascadeClassifier classifier("/usr/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml");

    for(;;)
    {
        cap >> img; // get a new img from camera
        cvtColor(img, grayImg, CV_BGR2GRAY); //灰度处理
        equalizeHist(grayImg,equalizeImg); //均衡化处理
        classifier.detectMultiScale(equalizeImg, faces); //检测人脸并返回在facas中
        if(faces.size())
        {
            rectangle(equalizeImg, faces[0], Scalar(255,255,255)); //绘制矩形框
            faceImg = equalizeImg(faces[0]);    
            imencode(".jpg", faceImg, jpgBuf);    //将图片编码为jpg格式后存到jpgBuf中
        }
        else
            cout<<"No face detected!"<<endl;

        imshow("video", equalizeImg); //在video窗口中展示图片 
        waitKey(40); //设置帧率(40ms读取一帧)
    }

    return 0;
}

重新编译运行即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值