opencv4 c++ 提取图片中的白色区域_OpenCV4.0实现人脸识别

本文介绍了如何使用OpenCV4.0的深度神经网络模块结合Openface模型实现人脸识别。首先,利用OpenCV的人脸检测模型检测图像中的人脸,接着通过Openface提取128维特征向量,最后基于余弦相似度进行人脸识别。代码实现包括加载网络、设置计算后台、人脸检测和比对等步骤。
摘要由CSDN通过智能技术生成
3b3d2437bf0f04cfbb44e607344921bf.gif

点击上方蓝字关注我们

关注:OpenCV干货与教程第一时间送达!

欢迎星标或者置顶【OpenCV学堂】

概述

OpenCV4.0深度神经网络模块,支持openface模型的导入,提取人脸的128特征向量,进行相似度比对,实现人脸识别。Openface模型的详细信息看这里

http://www.cv-foundation.org/openaccess/content_cvpr_2015/app/1A_089.pdf

主要原理是基于2015年CVPR的FaceNet网络的论文,去年的时候写过一篇文章介绍过它,想要了解详细信息的点击这里查看即可

OpenCV+Tensorflow实现实时人脸识别演示

主要思路

首先使用OpenCV4.0 DNN模块支持的人脸检测模型,实现对图像或者视频的人脸检测,然后对得到的人脸区域通过openface的预训练模型提取128个特征向量值,基于余弦相似度进行特征值比对,实现人脸识别。完整的流程可以图示如下:

16680efb5afa6a7a4b9b8cd5cab2392a.png

余弦相似公式与解释:

de332380371c4777702f63d83301cbcf.png

代码实现步骤

01

加载网络

需要先加载人脸检测与openface人脸识别网络模型,代码实现如下:

    String modelDesc = "D:/projects/opencv_tutorial/data/models/resnet/deploy.prototxt";
    String modelBinary = "D:/projects/opencv_tutorial/data/models/resnet/res10_300x300_ssd_iter_140000.caffemodel";
    String facemodel = "D:/projects/opencv_tutorial/data/models/face_detector/openface.nn4.small2.v1.t7";

    // 初始化网络
    Net net = readNetFromCaffe(modelDesc, modelBinary);
    Net netRecogn = readNetFromTorch(facemodel);

这两个模型的下载地址如下:

https://github.com/gloomyfish1998/opencv_tutorial/tree/master/data/models/face_detector

02

设置计算后台

OpenCV支持不同的计算后台,这里我们采用OpenVINO作为计算后台,可以实现加速计算,代码如下:

// 设置计算后台
Net netRecogn = readNetFromTorch(facemodel);
net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
net.setPreferableTarget(DNN_TARGET_CPU);

netRecogn.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
netRecogn.setPreferableTarget(DNN_TARGET_CPU);

// load face data
vector<vector<float>> face_data;
vector<string> labels;
vector<string> faces;
glob("D:/my_faces/zhigang", faces);
for (auto fn : faces) {
    vector<float> fv;
    Mat sample = imread(fn);
    recognize_face(sample, netRecogn, fv);
    face_data.push_back(fv);
    printf("file name : %s\n", fn.c_str());
    labels.push_back("zhigang");
}

faces.clear();
glob("D:/my_faces/balvin", faces);
for (auto fn : faces) {
    vector<float> fv;
    Mat sample = imread(fn);
    recognize_face(sample, netRecogn, fv);
    face_data.push_back(fv);
    printf("file name : %s\n", fn.c_str());
    labels.push_back("balvin");
}

if (net.empty() || netRecogn.empty())
{
    printf("could not load net...\n");
    return -1;
}

03

人脸检测

通过人脸检测网络实现人脸检测,代码实现如下:

// 输入数据调整
Mat inputBlob = blobFromImage(frame, inScaleFactor,
    Size(inWidth, inHeight), meanVal, false, false);
net.setInput(inputBlob, "data");

// 人脸检测
Mat detection = net.forward("detection_out");
vector<double> layersTimings;
double freq = getTickFrequency() / 1000;
double time = net.getPerfProfile(layersTimings) / freq;
Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());

04

人脸比对

把实时检测得到ROI区域与预先加载的人脸样本进行比较,找到距离最小的,如果小于阈值T,即为识别输出结果,解析人脸检测并实现人脸识别的代码如下:

for (int i = 0; i {
    // 置信度 0~1之间
    float confidence = detectionMat.at<float>(i, 2);
    if (confidence > confidenceThreshold)
    {
        int xLeftBottom = static_cast<int>(detectionMat.at<float>(i, 3) * frame.cols);
        int yLeftBottom = static_cast<int>(detectionMat.at<float>(i, 4) * frame.rows);
        int xRightTop = static_cast<int>(detectionMat.at<float>(i, 5) * frame.cols);
        int yRightTop = static_cast<int>(detectionMat.at<float>(i, 6) * frame.rows);

        Rect object((int)xLeftBottom, (int)yLeftBottom,
            (int)(xRightTop - xLeftBottom),
            (int)(yRightTop - yLeftBottom));
        if (object.width 5 || object.height 5) {
            continue;
        }
        // 截取人脸ROI区域
        Mat roi = frame(object);

        // 人脸比对,发现相似度最高的
        vector<float> curr_fv;
        recognize_face(roi, netRecogn, curr_fv);
        float minDist = 10;
        int index = -1;
        for (int i = 0; i             float dist = compare(curr_fv, face_data[i]);
            if (minDist > dist) {
                minDist = dist;
                index = i;
            }
        }

        // 阈值与显示识别结果
        printf("index : %d, dist: %.2f \n", index, minDist);
        if (index >= 0 && minDist 0.30) {
            putText(frame, labels[index].c_str(), Point(xLeftBottom, yLeftBottom-20),
                FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 0, 255));
        }
        rectangle(frame, object, Scalar(0, 255, 0));

        ss.str("");
        ss <        String conf(ss.str());
        String label = "Face: " + conf;
        int baseLine = 0;
        Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
        rectangle(frame, Rect(Point(xLeftBottom, yLeftBottom - labelSize.height),
            Size(labelSize.width, labelSize.height + baseLine)),
            Scalar(255, 255, 255), FILLED);
        putText(frame, label, Point(xLeftBottom, yLeftBottom),
            FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0));
    }
}

余弦相似比较

float compare(vector<float> &fv1, vector<float> fv2) {
    // 计算余弦相似, 0 ~ 1 距离,距离越小越相似,
    // 0表示夹角为0°,1表示夹角为90°
    float dot = 0;
    float sum2 = 0;
    float sum3 = 0;
    for (int i = 0; i         dot += fv1[i] * fv2[i];
        sum2 += pow(fv1[i], 2);
        sum3 += pow(fv2[i], 2);
    }
    float norm = sqrt(sum2)*sqrt(sum3);
    float similarity = dot / norm;
    float dist = acos(similarity) / CV_PI;
    return dist;
}

运行效果

f48e578fc1777c45cb500e737b47a78f.png

57c603c423e1aab1e3e638e764775f10.png长太丑,只能打点马赛克57c603c423e1aab1e3e638e764775f10.png

往期精选

OpenCV4系统化学习路线图与教程

OpenCV实现年龄与性别预测

OpenCV4.0 灰度图像彩色化

使用OpenVINO ToolKit 实时推断

OpenCV+Tensorflow实现实时人脸识别演示

对象检测网络中的NMS算法详解

欢迎扫码加入【OpenCV研习社】

原价99元,限时优惠只需69元

(优惠截止日期:2019年3月31号)

扫码即可加入学习(下载课程代码与资料)!

c2d002ba23af37e6f72bff1f1beb46ca.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现人脸识别的常用方法是利用人脸检测和人脸识别技术。在此基础上,可以使用C++OpenCV库来实现人脸识别。下面是一个简单的步骤: 1. 加载人脸检测器模型文件。OpenCV提供了Haar分类器和人脸识别模型文件,可以直接下载并使用。 2. 加载待检测的图片。 3. 对图片进行预处理,如灰度化、直方图均衡化等。 4. 使用人脸检测器模型文件检测人脸位置。 5. 利用人脸识别算法比对人脸特征,进行人脸识别。 以下是一个简单的C++代码示例: ```C++ #include <opencv2/opencv.hpp> #include <opencv2/face.hpp> using namespace cv; using namespace cv::face; int main() { // 加载人脸检测器模型文件 CascadeClassifier faceDetector("haarcascade_frontalface_default.xml"); // 加载人脸识别器模型文件 Ptr<LBPHFaceRecognizer> faceRecognizer = LBPHFaceRecognizer::create(); faceRecognizer->read("face_recognizer.xml"); // 加载待检测的图片 Mat img = imread("test.jpg"); // 对图片进行预处理 Mat grayImg; cvtColor(img, grayImg, COLOR_BGR2GRAY); equalizeHist(grayImg, grayImg); // 检测人脸位置 std::vector<Rect> faces; faceDetector.detectMultiScale(grayImg, faces, 1.1, 2, 0, Size(30, 30)); // 对每个检测到的人脸进行识别 for (int i = 0; i < faces.size(); i++) { Mat faceImg = grayImg(faces[i]); // 比对人脸特征,进行人脸识别 int label = -1; double confidence = 0; faceRecognizer->predict(faceImg, label, confidence); // 在图片标出人脸位置和识别结果 rectangle(img, faces[i], Scalar(255, 0, 0), 2); putText(img, format("Label: %d, Confidence: %.2f", label, confidence), Point(faces[i].x, faces[i].y - 10), FONT_HERSHEY_PLAIN, 1.0, Scalar(255, 0, 0), 2); } // 显示结果 imshow("Face Recognition", img); waitKey(0); return 0; } ``` 需要注意的是,人脸识别的准确率和速度受到多种因素的影响,如人脸图像的质量、人脸识别算法的选择和参数等。在实际应用,需要根据具体需求进行优化和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值