opencv进阶 ——(十)图像处理之基于dlib人脸检测与识别

        Dlib是一个功能丰富的C++库,设计用于构建复杂的软件系统,尤其在机器学习、计算机视觉和数值计算等领域有着广泛的应用。以下是对Dlib的简要介绍:

  1. 特性

    • 机器学习算法:Dlib包含了各种机器学习算法,如支持向量机(SVMs)、决策树、随机森林、神经网络等。
    • 深度学习框架:Dlib有一个简洁而强大的深度学习接口,允许开发者定义和训练自己的卷积神经网络(CNNs)。
    • 图像处理:提供图像处理和计算机视觉工具,如面部特征检测、物体检测、图像变换等。
    • 数学工具:提供线性代数、优化算法和统计工具,适合数值计算任务。
    • 实用工具:包括日志记录、线程管理、内存管理、序列化等功能。
  2. 文档和示例

    • 全面文档:Dlib的每个类和函数都有详细的文档说明,方便开发者理解和使用。
    • 调试支持:在调试模式下,Dlib提供帮助调试代码的功能,有助于快速定位问题。
    • 示例代码:官方提供许多实例代码,便于学习和参考。
  3. 平台兼容性

    • 跨平台:Dlib可以在Windows、Mac OS和Linux等多种操作系统上编译和运行。
    • 独立性:不依赖于第三方库,易于集成到项目中,编译过程简单。
  4. 开源许可

    • BSD许可证:Dlib采用宽松的BSD许可证,允许在商业和非商业项目中免费使用。
  5. 应用领域

    • 工业界:在机器人、嵌入式设备、移动应用等领域有应用。
    • 学术界:在研究项目中作为强大的工具,用于实验和原型设计。

环境搭建

        源码地址:https://github.com/davisking/dlib

        模型下载:http://dlib.net/files/

人脸检测

        

#include <dlib/image_processing/frontal_face_detector.h>
#include <dlib/image_processing.h>
#include <dlib/opencv.h>
#include <opencv2/opencv.hpp>

void FaceDetector(cv::Mat& img)
{
    // 加载人脸检测器
    auto detector = dlib::get_frontal_face_detector();

   // 将图片转换为dlib图像格式
    dlib::cv_image<dlib::bgr_pixel> cimg(cvIplImage(img));
 
    // 检测人脸
    std::vector<dlib::rectangle> dets = detector(cimg); 
    std::cout << "number of faces detected:" << dets.size() << std::endl;

}

人脸关键点检测

关键点分布

示例代码

#include <dlib/image_processing/frontal_face_detector.h>
#include <dlib/image_processing/render_face_detections.h>
#include <dlib/image_processing.h>
#include <dlib/opencv.h>

 
using namespace dlib;
using namespace std;
 
int main()
{
    // 加载人脸检测器
    frontal_face_detector detector = get_frontal_face_detector();
 
    // 加载人脸关键点检测器
    shape_predictor sp;
    deserialize("shape_predictor_68_face_landmarks.dat") >> sp;
 
    // 读取图片
    cv::Mat img = cv::imread("image.jpg");
 
    // 将图片转换为dlib图像格式
    cv_image<bgr_pixel> cimg(img);
 
    // 检测人脸
    std::vector<rectangle> faces = detector(cimg);
 
    // 选择最大的人脸
    int max_area = 0;
    rectangle max_face;
    for (int i = 0; i < faces.size(); i++)
    {
        int area = faces[i].area();
        if (area > max_area)
        {
            max_area = area;
            max_face = faces[i];
        }
    }
 
    // 检测关键点
    full_object_detection shape = sp(cimg, max_face);
 

}


人脸识别

参考代码

#include <dlib/dnn.h>
#include <dlib/gui_widgets.h>
#include <dlib/clustering.h>
#include <dlib/string.h>
#include <dlib/image_io.h>
#include <dlib/image_processing/frontal_face_detector.h>

using namespace dlib;
using namespace std;

// ----------------------------------------------------------------------------------------

// The next bit of code defines a ResNet network.  It's basically copied
// and pasted from the dnn_imagenet_ex.cpp example, except we replaced the loss
// layer with loss_metric and made the network somewhat smaller.  Go read the introductory
// dlib DNN examples to learn what all this stuff means.
//
// Also, the dnn_metric_learning_on_images_ex.cpp example shows how to train this network.
// The dlib_face_recognition_resnet_model_v1 model used by this example was trained using
// essentially the code shown in dnn_metric_learning_on_images_ex.cpp except the
// mini-batches were made larger (35x15 instead of 5x5), the iterations without progress
// was set to 10000, and the training dataset consisted of about 3 million images instead of
// 55.  Also, the input layer was locked to images of size 150.
template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET>
using residual = add_prev1<block<N,BN,1,tag1<SUBNET>>>;

template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET>
using residual_down = add_prev2<avg_pool<2,2,2,2,skip1<tag2<block<N,BN,2,tag1<SUBNET>>>>>>;

template <int N, template <typename> class BN, int stride, typename SUBNET> 
using block  = BN<con<N,3,3,1,1,relu<BN<con<N,3,3,stride,stride,SUBNET>>>>>;

template <int N, typename SUBNET> using ares      = relu<residual<block,N,affine,SUBNET>>;
template <int N, typename SUBNET> using ares_down = relu<residual_down<block,N,affine,SUBNET>>;

template <typename SUBNET> using alevel0 = ares_down<256,SUBNET>;
template <typename SUBNET> using alevel1 = ares<256,ares<256,ares_down<256,SUBNET>>>;
template <typename SUBNET> using alevel2 = ares<128,ares<128,ares_down<128,SUBNET>>>;
template <typename SUBNET> using alevel3 = ares<64,ares<64,ares<64,ares_down<64,SUBNET>>>>;
template <typename SUBNET> using alevel4 = ares<32,ares<32,ares<32,SUBNET>>>;

using anet_type = loss_metric<fc_no_bias<128,avg_pool_everything<
                            alevel0<
                            alevel1<
                            alevel2<
                            alevel3<
                            alevel4<
                            max_pool<3,3,2,2,relu<affine<con<32,7,7,2,2,
                            input_rgb_image_sized<150>
                            >>>>>>>>>>>>;

// ----------------------------------------------------------------------------------------

std::vector<matrix<rgb_pixel>> jitter_image(
    const matrix<rgb_pixel>& img
);

// ----------------------------------------------------------------------------------------

int main(int argc, char** argv) try
{
    if (argc != 2)
    {
        cout << "Run this example by invoking it like this: " << endl;
        cout << "   ./dnn_face_recognition_ex faces/bald_guys.jpg" << endl;
        cout << endl;
        cout << "You will also need to get the face landmarking model file as well as " << endl;
        cout << "the face recognition model file.  Download and then decompress these files from: " << endl;
        cout << "http://dlib.net/files/shape_predictor_5_face_landmarks.dat.bz2" << endl;
        cout << "http://dlib.net/files/dlib_face_recognition_resnet_model_v1.dat.bz2" << endl;
        cout << endl;
        return 1;
    }

    // The first thing we are going to do is load all our models.  First, since we need to
    // find faces in the image we will need a face detector:
    frontal_face_detector detector = get_frontal_face_detector();
    // We will also use a face landmarking model to align faces to a standard pose:  (see face_landmark_detection_ex.cpp for an introduction)
    shape_predictor sp;
    deserialize("shape_predictor_5_face_landmarks.dat") >> sp;
    // And finally we load the DNN responsible for face recognition.
    anet_type net;
    deserialize("dlib_face_recognition_resnet_model_v1.dat") >> net;

    matrix<rgb_pixel> img;
    load_image(img, argv[1]);
    // Display the raw image on the screen
    image_window win(img); 

    // Run the face detector on the image of our action heroes, and for each face extract a
    // copy that has been normalized to 150x150 pixels in size and appropriately rotated
    // and centered.
    std::vector<matrix<rgb_pixel>> faces;
    for (auto face : detector(img))
    {
        auto shape = sp(img, face);
        matrix<rgb_pixel> face_chip;
        extract_image_chip(img, get_face_chip_details(shape,150,0.25), face_chip);
        faces.push_back(move(face_chip));
        // Also put some boxes on the faces so we can see that the detector is finding
        // them.
        win.add_overlay(face);
    }

    if (faces.size() == 0)
    {
        cout << "No faces found in image!" << endl;
        return 1;
    }

    // This call asks the DNN to convert each face image in faces into a 128D vector.
    // In this 128D vector space, images from the same person will be close to each other
    // but vectors from different people will be far apart.  So we can use these vectors to
    // identify if a pair of images are from the same person or from different people.  
    std::vector<matrix<float,0,1>> face_descriptors = net(faces);


    // In particular, one simple thing we can do is face clustering.  This next bit of code
    // creates a graph of connected faces and then uses the Chinese whispers graph clustering
    // algorithm to identify how many people there are and which faces belong to whom.
    std::vector<sample_pair> edges;
    for (size_t i = 0; i < face_descriptors.size(); ++i)
    {
        for (size_t j = i; j < face_descriptors.size(); ++j)
        {
            // Faces are connected in the graph if they are close enough.  Here we check if
            // the distance between two face descriptors is less than 0.6, which is the
            // decision threshold the network was trained to use.  Although you can
            // certainly use any other threshold you find useful.
            if (length(face_descriptors[i]-face_descriptors[j]) < 0.6)
                edges.push_back(sample_pair(i,j));
        }
    }
    std::vector<unsigned long> labels;
    const auto num_clusters = chinese_whispers(edges, labels);
    // This will correctly indicate that there are 4 people in the image.
    cout << "number of people found in the image: "<< num_clusters << endl;


    // Now let's display the face clustering results on the screen.  You will see that it
    // correctly grouped all the faces. 
    std::vector<image_window> win_clusters(num_clusters);
    for (size_t cluster_id = 0; cluster_id < num_clusters; ++cluster_id)
    {
        std::vector<matrix<rgb_pixel>> temp;
        for (size_t j = 0; j < labels.size(); ++j)
        {
            if (cluster_id == labels[j])
                temp.push_back(faces[j]);
        }
        win_clusters[cluster_id].set_title("face cluster " + cast_to_string(cluster_id));
        win_clusters[cluster_id].set_image(tile_images(temp));
    }




    // Finally, let's print one of the face descriptors to the screen.  
    cout << "face descriptor for one face: " << trans(face_descriptors[0]) << endl;

    // It should also be noted that face recognition accuracy can be improved if jittering
    // is used when creating face descriptors.  In particular, to get 99.38% on the LFW
    // benchmark you need to use the jitter_image() routine to compute the descriptors,
    // like so:
    matrix<float,0,1> face_descriptor = mean(mat(net(jitter_image(faces[0]))));
    cout << "jittered face descriptor for one face: " << trans(face_descriptor) << endl;
    // If you use the model without jittering, as we did when clustering the bald guys, it
    // gets an accuracy of 99.13% on the LFW benchmark.  So jittering makes the whole
    // procedure a little more accurate but makes face descriptor calculation slower.


    cout << "hit enter to terminate" << endl;
    cin.get();
}
catch (std::exception& e)
{
    cout << e.what() << endl;
}

// ----------------------------------------------------------------------------------------

std::vector<matrix<rgb_pixel>> jitter_image(
    const matrix<rgb_pixel>& img
)
{
    // All this function does is make 100 copies of img, all slightly jittered by being
    // zoomed, rotated, and translated a little bit differently. They are also randomly
    // mirrored left to right.
    thread_local dlib::rand rnd;

    std::vector<matrix<rgb_pixel>> crops; 
    for (int i = 0; i < 100; ++i)
        crops.push_back(jitter_image(img,rnd));

    return crops;
}

其中关键点检测shape_predictor_5_face_landmarks.dat模型也可以改成shape_predictor_68_face_landmarks.dat

人脸识别过程中,需要根据预先录入的人脸信息得到人脸关键点数组

std::vector<matrix<rgb_pixel>> faces;

然后得到人脸描述信息数组

std::vector<matrix<float,0,1>> face_descriptors = net(faces);

同样可以以这种形式得到当前人脸的描述信息,然后去数组中匹配最接近的人脸信息

        length(face_descriptors[i]-face_descriptors[j])

计算人脸描述的差异,值越小标识越接近。

效果展示

人脸检测

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/681562.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

友思特应用 | 慧眼识珠:如何实现无障碍高光谱成像?

导读 近红外相机可帮助人眼捕捉不同材料之间光谱特征的微小差异。友思特 Monarch 微型可调近红外相机以其小体积、低成本、高性能&#xff0c;3步即可快速实现各种材料的分类应用。 多光谱成像 每个物品都是由不同的化学物质组成的&#xff0c;这些化学物质的反射随光谱带的不…

机器学习18个核心算法模型

1. 线性回归&#xff08;Linear Regression&#xff09; 用于建立自变量&#xff08;特征&#xff09;和因变量&#xff08;目标&#xff09;之间的线性关系。 核心公式&#xff1a; 简单线性回归的公式为&#xff1a; , 其中 是预测值&#xff0c; 是截距&#xff0c; 是斜…

ASCE(美国土木工程师学会)文献校外去哪里查找下载

今天要讲的数据库是ASCE&#xff08;美国土木工程师学会&#xff09;&#xff0c;该数据库每年出版5万多页的专业期刊、杂志、会议录、专著、技术报告、实践手册和标准等。目前&#xff0c;ASCE数据库中包含35种期刊(1983年至今)、近700卷会议录( 1996年至今)、Civil Engineeri…

10分钟了解KEDA高效弹性伸缩方案

文章目录 为什么需要 KEDA &#xff1f;KEDA 的原理哪些场景适合使用 KEDA &#xff1f;微服务多级调用任务执行&#xff08;生产者与消费者&#xff09;周期性规律 配置实践KEDA安装helm 方式安装 策略配置scaledobject 对象说明 问题记录 为什么需要 KEDA &#xff1f; HPA …

五、nodejs存储图片

nodejs存储图片 // 静态托管和数据库创建 创建数据库 新建Public进行静态托管 新建个img的文件夹 在index.js里 // 托管静态 app.use(/public, express.static(./Public))//托管静态资源 /*** 1.引入一个express框架* 2.在加载所有服务模块前&#xff0c;要先连接数据库* …

AST 在前端开发中的应用与实践:从代码分析到自动化转换

抽象语法树&#xff08;AST&#xff0c;Abstract Syntax Tree&#xff09;在前端开发中有着广泛的应用。它是编译器和工具链的核心组件&#xff0c;使得代码分析、转换、优化等操作成为可能。在前端开发中&#xff0c;AST 主要用于代码编译和转译、代码优化、代码分析、代码格式…

vue对图片进行裁剪

安装依赖&#xff1a; npm install cropperjs -save <template><div class"bigBox"><h3>预览</h3><!-- 裁剪按钮--><el-button click"sureSava">裁剪</el-button><el-button click"confirm">确…

元宇宙3D品牌营销虚拟场景提升客户对企业的黏性

在这个充满创意与想象的3D元宇宙时代&#xff0c;我们为您推出了全新的3D元宇宙场景在线制作编辑平台&#xff0c;让您轻松构建专属的虚拟展厅&#xff0c;展现无限可能。 3D元宇宙场景在线制作编辑平台允许您快速完成空间设计&#xff0c;根据您的个性化需求&#xff0c;自由设…

1.1 QT随手简记(一)

QT学习篇1 1. QT简介 Qt是一个跨平台的库&#xff0c;它提供了丰富的功能&#xff0c;用于开发GUI应用程序、桌面应用程序、移动应用程序和嵌入式应用程序。Qt由Qt公司维护&#xff0c;是一个开源项目&#xff0c;支持多种操作系统&#xff0c;包括Windows、Linux、Mac OS等。…

Django路由与会话深度探索:静态、动态路由分发,以及Cookie与Session的奥秘

系列文章目录 Django入门全攻略&#xff1a;从零搭建你的第一个Web项目Django ORM入门指南&#xff1a;从概念到实践&#xff0c;掌握模型创建、迁移与视图操作Django ORM实战&#xff1a;模型字段与元选项配置&#xff0c;以及链式过滤与QF查询详解Django ORM深度游&#xff…

clickhouse(十五、存储优化实践)

文章目录 背景问题定位优化方式排序键设计写入顺序压缩算法 DoubleDeltaLowCardinality避免使用Nullable 总结 背景 clickhouse集群容量告警&#xff0c;项目中某些表占据大量的存储空间&#xff0c;借此机会对ck的存储优化进行实践学习&#xff0c;并通过多种方式测试验证优化…

元宇宙NFG交易市场:减少出入金的税和消泡沫

在元宇宙的宏伟画卷中&#xff0c;NFG&#xff08;非同质化商品&#xff09;以其独特魅力逐渐崭露头角&#xff0c;成为连接现实世界与数字世界的桥梁。NFG不仅仅是一种商品&#xff0c;更是一种创新的商业模式&#xff0c;为资金的流动与税收优惠带来了新的可能。 首先&#…

QT error: allocation of incomplete type ‘Ui::Server‘

目录 前言 报错内容&#xff1a; 过程解析&#xff1a; 原因分析&#xff1a; daisy.skye的博客 QT合集http://t.csdnimg.cn/wEVbu 前言 最近又开始需要做上位机了&#xff0c;要知道qt上位机对我来说已经3年没有接触了&#xff0c;最开始接触还是毕业时工作中的简单学习和…

【预计IEEE出版】第四届电子信息工程与计算机技术国际学术会议(EIECT 2024)

第四届电子信息工程与计算机技术国际学术会议&#xff08;EIECT 2024&#xff09; 2024 4th International Conference on Electronic Information Engineering and Computer Technology 2024年11月15-17日 | 中国 深圳 #往届均已成功见刊、EI检索;先投稿&#xff0c;先送审…

CSS学习|css三种导入方式、基本选择器、层次选择器、结构伪类选择器、属性选择器、字体样式、文本样式

第一个css程序 css程序都是在style标签中书写 打开该网页&#xff0c;可以看到h1标签中的我是标题被渲染成了红色 可以在同级目录下创建一个css目录&#xff0c;专门存放css文件&#xff0c;可以和html分开编写 然后在html页面中&#xff0c;利用link标签以及css文件地址&…

【AI大模型】基于Langchain和Openai借口实现英文翻译中文应用

&#x1f680; 作者 &#xff1a;“大数据小禅” &#x1f680; 文章简介 &#xff1a;本专栏后续将持续更新大模型相关文章&#xff0c;从开发到微调到应用&#xff0c;需要下载好的模型包可私。 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 目…

C++ primer例子1实现

问题 代码 Sales_item.h #include<iostream> #include<string> class Sales_item {public:Sales_item(){};Sales_item(std::string insid, int num, double price);friend std::istream& operator>>(std::istream& is, Sales_item& item);frie…

LeetCode-43. 字符串相乘【数学 字符串 模拟】

LeetCode-43. 字符串相乘【数学 字符串 模拟】 题目描述&#xff1a;解题思路一&#xff1a;模拟乘法&#xff0c;两个数中每一位数相乘的时候乘上他们各自的进制数&#xff0c;之后求和。循环时&#xff0c;分别记录各自的进制数背诵版&#xff1a;解题思路三&#xff1a;0 题…

课程标准包括哪些内容

在教育的广阔天地中&#xff0c;课程标准如同一座灯塔&#xff0c;照亮了教师们的教学之路。那么&#xff0c;这座灯塔究竟照亮了哪些关键领域呢&#xff1f; 课程标准为我们指明了教学目标。这些目标是教学活动的航标&#xff0c;指引我们如何根据学生的认知水平和学习需求&a…

防火墙是什么?探讨部署Web防火墙的必要性

如今&#xff0c;多云环境、API安全功能扩展、合作伙伴集成即时可用、可用性和可视化增强以及提高自动化程度已经成为基本要求。伴随企业应用架构的迁移&#xff0c;在用户端&#xff0c;需要在部署环境不断扩展但人员技能有限的情况下&#xff0c;保护数量日益增长的应用安全。…