opencv學習之路(41)、人臉識別

1、人臉檢測並採集我的圖像

//take_photo.cpp
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;

void take_photo() {
    VideoCapture cap(0); //打開攝像頭
    if (!cap.isOpened())
        return;

    //加載級聯檢測器
    CascadeClassifier cascade;
    cascade.load("F:/opencv3.2/Release_x64/etc/haarcascades/haarcascade_frontalface_alt_tree.xml");

    Mat frame;
    vector<Rect>faces;
    int count = 0;
    while (cap.read(frame))        //至關於cap >> frame
    {
        cascade.detectMultiScale(frame, faces, 1.1, 1, 0, Size(100, 100), Size(400, 400));//檢測是否有人臉
        for (int i = 0; i < faces.size(); i++)
        {
            if (count % 10 == 0) {    //每10幀保存一次人臉圖像
                Mat dst;
                resize(frame(faces[i]), dst, Size(92, 112));//設置人臉圖像大小
                cvtColor(dst, dst, COLOR_BGR2GRAY);//轉爲灰度圖節省計算
                imwrite(format("att_faces/s41/pic%d.jpg", count / 10), dst);
            }
            rectangle(frame, faces[i], Scalar(0, 255, 0));
        }
        imshow("video", frame);

        //按下任意鍵退出攝像頭(waitkey在本系統環境下默認爲255),或者是保存了20張人臉圖片後,退出
        if (waitKey(50) != 255 || count / 10>20)
            break;
        count++;
    }
    cap.release();
    destroyAllWindows();//關閉全部窗口
}

 運行程序,打開攝像頭後會自動保存人臉圖像,頭不要晃動,表情變化便可,對於不合適的照片還需進行篩選。ios

 2、基於特徵臉算法的人臉識別

//face_recognition.cpp
#include <opencv2/opencv.hpp>
#include <opencv2/face.hpp>

using namespace cv;
using namespace cv::face;
using namespace std;

double face_recognition() {
    //讀取文件,轉換爲數據流
    string filename = string("at.txt");
    ifstream file(filename.c_str(), ifstream::in);
    if (!file)
        cout << "error" << endl;

    string line, path, classlabel;
    vector<Mat>image;
    vector<int>labels;
    char separator = ';';
    while (getline(file, line))
    {
        stringstream liness(line);
        getline(liness, path, separator);
        getline(liness, classlabel);
        if (!path.empty() && !classlabel.empty())
        {
            //cout << "path:" << path<< endl;
            image.push_back(imread(path, 0));
            labels.push_back(atoi(classlabel.c_str()));
        }
    }
    if (image.size() < 1 || labels.size() < 1)
        cout << "invalid image path..." << endl;

    //最後一我的爲測試樣本
    Mat testSample = image[image.size() - 1];
    int testLabel = labels[labels.size() - 1];
    image.pop_back();
    labels.pop_back();

    //EigenFace算法的模型訓練
    Ptr<BasicFaceRecognizer>model = createEigenFaceRecognizer();
    model->train(image, labels);

    //對樣本進行識別
    int predictLabel = model->predict(testSample);
    cout << "actual label:" << testLabel << ",predict label:" << predictLabel << endl;

    //加載級聯檢測器
    CascadeClassifier cascade;
    cascade.load("haarcascade_frontalface_alt_tree.xml");//識別時用alt_tree分類器,寧肯漏檢也不誤檢

    //打開攝像頭
    VideoCapture cap(0);
    if (!cap.isOpened())
        cout << "error...";

    Mat frame;
    vector<Rect>faces;
    int correct = 0, total = 0;
    while (cap.read(frame))        //至關於cap >> frame,讀取攝像頭的每一幀
    {
        cascade.detectMultiScale(frame, faces, 1.1, 1, 0, Size(80, 100), Size(380, 400));//檢測是否有人臉
        for (int i = 0; i < faces.size(); i++)
        {
            Mat roi = frame(faces[i]);
            cvtColor(roi, roi, COLOR_BGR2GRAY);
            resize(roi, testSample, testSample.size());
            int label = model->predict(testSample);
            rectangle(frame, faces[i], Scalar(0, 255, 0));
            if (label == 41)
            {
                putText(frame, "ZhangChunFu", faces[i].tl(), FONT_HERSHEY_COMPLEX, 1.0, Scalar(0, 0, 255));
                correct++;
            }
            else
                putText(frame, format("%d", label), faces[i].tl(), CV_FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0, 0, 255));
        }
        total++;
        imshow("人臉識別——MR.Zhang", frame);
        if (waitKey(50) == 27)
            break;
    }

    cap.release();
    destroyAllWindows();//關閉全部窗口
    waitKey(0);

    double rate = (1.0*correct) / total;
    return rate;//返回正確率
}
//main.cpp
#include <opencv2/opencv.hpp>
#include <opencv2/face.hpp>
#include <iostream>

using namespace cv;
using namespace cv::face;
using namespace std;

void take_photo();
double face_recognition();

void main() {
    int flag;
    double rate;
    cout << "歡迎使用人臉識別系統(1表明錄入人臉,2表明識別人臉),請輸入您的選擇:" << endl;
    cin >> flag;
    cout << "請稍等片刻……"<<endl;
    switch (flag)
    {
    case 1:take_photo();
        return;
    case 2:
        rate=face_recognition();
        break;
    default:
        break;
    }
    cout << "識別率:" << rate << endl;
    system("pause");

}

相關文章
相關標籤/搜索