NDK 開發實戰 - 實時人臉檢測和識別

關於人臉檢測和識別,應用的範圍是很是廣的,其實以前的《NDK開發前奏 - 實現支付寶人臉識別功能》 也有提到,只是那時並未具體的去分析算法和實現原理,這裏筆者打算一步一步來分析和實現人臉識別,首先咱們得要明確人臉檢測和人臉識別是兩個不一樣的概念,人臉檢測是檢測有人臉,人臉識別是匹配你是你,他們所採用的算法也是不同的,這篇文章是基於人臉檢測來實現人臉識別。咱們先來看下已經實現了的人臉檢測效果: 算法

實時人臉檢測

人臉馬賽克你們能夠忽略,並非這裏要關注的內容,是由於長得太帥了怕你們嫉妒。馬賽克效果實現你們能夠參考《圖形圖像處理 - 手寫 QQ 說說圖片處理效果》。首先咱們不妨來思考一下,要實現像支付寶的人臉識別和員工刷臉簽到等等,這樣的一些應用功能,咱們須要用到哪些知識?須要通過哪些步驟呢?其實這裏分爲兩步,第一步是樣本數據採集,第二步是檢測和匹配。不過咱們得先來看幾個概念:均值,標準差,協方差矩陣,特徵值,特徵向量,PCA降維。bash

1. 均值,標準差,協方差矩陣ui

這幾個都是機率論中的概念,咱們隨便舉一個例子來算下便可,假設個人 Mat 數據以下:spa

Mat src = (Mat_<int>(3, 3) << 50, 50, 50, 60, 60, 60, 70, 70, 70);
複製代碼

均值:[60]code

均值

標準差:[8.164965809277252]orm

標準差

協方差矩陣:[200, 200, 200; 200, 200, 200; 200, 200, 200]cdn

協方差矩陣

2. 特徵值,特徵向量視頻

關於特徵值與特徵向量這是線性代數的概念,仍是老套路拿個例子過來算下,能算出來就能夠了,同時你們也能夠參考這篇文章: en.wikipedia.org/wiki/Eigenv…xml

圖片來源於百度經驗

圖片來源於百度經驗

圖片來源於百度經驗

3. PCA降維blog

人臉識別確定須要採集人臉樣本,也就是相機採集過來的 Mat 數據,那麼大量的數據怎麼處理呢?這裏就須要 PCA 降維了:

  • 把原始數據中每一個樣本用一個向量表示,而後把全部樣本組合起來構成一個矩陣。固然了,爲了不樣本的單位的影響,樣本集須要標準化。
  • 求該矩陣的協方差矩陣
  • 求步驟2中獲得的協方差矩陣的特徵值和特徵向量。
  • 將求出的特徵向量按照特徵值的大小進行組合造成一個映射矩陣,並根據指定的 PCA 保留的特徵個數取出映射矩陣的前n行或者前n列做爲最終的映射矩陣。
  • 用步驟4的映射矩陣對原始數據進行映射,達到數據降維的目的。

4. 樣本訓練

接下來就是代碼層面的東西了,代碼是很簡單的就那麼幾句話,但關鍵其實仍是在於理解裏面的原理:

FaceDetection_trainingPattern(JNIEnv *env, jobject instance) {
    // 訓練樣本,這一步是在數據採集作的
    // train it
    vector<Mat> faces;
    vector<int> labels;

    // 樣本比較少
    for (int i = 1; i <= 5; ++i) {
        for (int j = 1; j <= 5; ++j) {
            Mat face = imread(format("/storage/emulated/0/s%d/%d.pgm", i, j), 0);
            if (face.empty()) {
                LOGE("face mat is empty");
                continue;
            }
            // 確保大小一致
            resize(face, face, Size(128, 128));
            faces.push_back(face);
            labels.push_back(i);
        }
    }

    for (int i = 1; i <= 8; ++i) {
        Mat face = imread(format("/storage/emulated/0/face_%d.png", i), 0);
        if (face.empty()) {
            LOGE("face mat is empty");
            continue;
        }
        resize(face, face, Size(128, 128));
        faces.push_back(face);
        labels.push_back(11);
    }

    // 訓練方法
    Ptr<BasicFaceRecognizer> model = EigenFaceRecognizer::create();
    // 採集了八張,同一我的 label 同樣
    model->train(faces, labels);
    // 訓練樣本是 xml ,本地
    model->save("/storage/emulated/0/face_darren_pattern.xml");// 存的是處理的特徵數據
    LOGE("樣本訓練成功");
}
複製代碼

5. 匹配識別

FaceDetection_faceDetection(JNIEnv *env, jobject instance,
                                                         jlong nativeObj) {
    Mat *src = reinterpret_cast<Mat *>(nativeObj);

    int width = src->rows;
    int height = src->cols;

    Mat grayMat;
    // 2. 轉成灰度圖,提高運算速度,灰度圖所對應的 CV_8UC1 單顏色通道,信息量少 0-255 1u
    cvtColor(*src, grayMat, COLOR_BGRA2GRAY);

    // 4. 檢測人臉,這是個大問題
    // 參數 1.1 會採起上採樣和降採樣 ,縮放比例
    // 參數 3 檢測多少次
    // 參數 Size(width / 2, height / 2) 最小臉的大小
    std::vector<Rect> faces;
    cascadeClassifier.detectMultiScale(grayMat, faces, 1.1, 3, 0, Size(width / 2, height / 2));

    if (faces.size() != 1) {
        mosaicFace(*src);
        return;
    }

    // 把臉框出來
    Rect faceRect = faces[0];
    rectangle(*src, faceRect, Scalar(255, 0, 0, 255), 4, LINE_AA);

    // 不斷檢測,錄入 10 張,張張嘴巴,眨眨眼睛 ,保證準確率
    // 還須要注意一點,確保人臉大小一致,reSize(128,128) ,確保收集到的人臉眼睛儘可能在一條線上
    // 與服務端進行比對,是否是我

    // 用一個計數器,這裏咱們作及時的
    Mat face = (*src)(faceRect).clone();
    resize(face, face, Size(128, 128));
    cvtColor(face, face, COLOR_BGRA2GRAY);
    // 直方均衡,harr 檢測人臉
    int label = model->predict(face);
    // 訓練的時候存的是 11
    if (label == 11) {
        // 識別到了本身
        LOGE("識別到了本身");
        putText(*src, "Darren", Point(faceRect.x + 20, faceRect.y - 20),
                HersheyFonts::FONT_HERSHEY_COMPLEX, 1, Scalar(255, 0, 0, 255),2,LINE_AA);
    } else {
        // 不是本身
        LOGE("不是本身");
        putText(*src, "UnKnow", Point(faceRect.x + 20, faceRect.y - 20),
                HersheyFonts::FONT_HERSHEY_COMPLEX, 1, Scalar(255, 0, 0, 255),2,LINE_AA);
    }
    // 速度, 準確率, 人臉儘可能正常
    mosaicFace((*src)(faceRect));
}
複製代碼

實時人臉識別

視頻地址:pan.baidu.com/s/1lF92ev7_… 視頻密碼:jc4k

相關文章
相關標籤/搜索