c++ cpp cmake opencv 深度学习模型 推理 前向部署 代码示例示意

news2024/11/23 16:31:09

参考实现:

https://github.com/spmallick/learnopencv/tree/master/AgeGender

文件结构:

具体实现:

#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/dnn.hpp>
#include <tuple>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <iterator>
using namespace cv;
using namespace cv::dnn;
using namespace std;

tuple<Mat, vector<vector<int>>> getFaceBox(Net net, Mat &frame, double conf_threshold)
{
    Mat frameOpenCVDNN = frame.clone();
    int frameHeight = frameOpenCVDNN.rows;
    int frameWidth = frameOpenCVDNN.cols;
    double inScaleFactor = 1.0;
    Size size = Size(300, 300);
    // std::vector<int> meanVal = {104, 117, 123};
    Scalar meanVal = Scalar(104, 117, 123);

    cv::Mat inputBlob;
    inputBlob = cv::dnn::blobFromImage(frameOpenCVDNN, inScaleFactor, size, meanVal, true, false);

    net.setInput(inputBlob, "data");
    cv::Mat detection = net.forward("detection_out");

    cv::Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());

    vector<vector<int>> bboxes;

    for(int i = 0; i < detectionMat.rows; i++)
    {
        float confidence = detectionMat.at<float>(i, 2);

        if(confidence > conf_threshold)
        {
            int x1 = static_cast<int>(detectionMat.at<float>(i, 3) * frameWidth);
            int y1 = static_cast<int>(detectionMat.at<float>(i, 4) * frameHeight);
            int x2 = static_cast<int>(detectionMat.at<float>(i, 5) * frameWidth);
            int y2 = static_cast<int>(detectionMat.at<float>(i, 6) * frameHeight);
            vector<int> box = {x1, y1, x2, y2};
            bboxes.push_back(box);
            cv::rectangle(frameOpenCVDNN, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(0, 255, 0),2, 4);
        }
    }

    return make_tuple(frameOpenCVDNN, bboxes);
}

int main(int argc, char** argv)
{
    string faceProto = "opencv_face_detector.pbtxt";
    string faceModel = "opencv_face_detector_uint8.pb";

    string ageProto = "age_deploy.prototxt";
    string ageModel = "age_net.caffemodel";

    string genderProto = "gender_deploy.prototxt";
    string genderModel = "gender_net.caffemodel";

    Scalar MODEL_MEAN_VALUES = Scalar(78.4263377603, 87.7689143744, 114.895847746);

    vector<string> ageList = {"(0-2)", "(4-6)", "(8-12)", "(15-20)", "(25-32)",
      "(38-43)", "(48-53)", "(60-100)"};

    vector<string> genderList = {"Male", "Female"};


    cout << "USAGE : ./AgeGender <videoFile> " << endl;
    cout << "USAGE : ./AgeGender <device> " << endl;
    cout << "USAGE : ./AgeGender <videoFile> <device>" << endl;

    string device = "cpu";

    string videoFile = "0";

    // Take arguments from commmand line
    if (argc == 2)
    {   
      if((string)argv[1] == "gpu")
        device = "gpu";
      else if((string)argv[1] == "cpu")
        device = "cpu";
      else 
      videoFile = argv[1];
    }
    else if (argc == 3)
    {
        videoFile = argv[1];
        if((string)argv[2] == "gpu")
            device = "gpu";
    }

    // Load Network
    Net ageNet = readNet(ageModel, ageProto);
    Net genderNet = readNet(genderModel, genderProto);
    Net faceNet = readNet(faceModel, faceProto);

    if (device == "cpu")
    {
        cout << "Using CPU device" << endl;
        ageNet.setPreferableBackend(DNN_TARGET_CPU);
        
        genderNet.setPreferableBackend(DNN_TARGET_CPU);

        faceNet.setPreferableBackend(DNN_TARGET_CPU);
    }
    else if (device == "gpu")
    {
        cout << "Using GPU device" << endl;
        ageNet.setPreferableBackend(DNN_BACKEND_CUDA);
        ageNet.setPreferableTarget(DNN_TARGET_CUDA);

        genderNet.setPreferableBackend(DNN_BACKEND_CUDA);
        genderNet.setPreferableTarget(DNN_TARGET_CUDA);

        faceNet.setPreferableBackend(DNN_BACKEND_CUDA);
        faceNet.setPreferableTarget(DNN_TARGET_CUDA);
    }


    VideoCapture cap;
    if (videoFile.length() > 1)
        cap.open(videoFile);
    else
        cap.open(0);
    int padding = 20;
    while(waitKey(1) < 0) {
      // read frame
      Mat frame;
      cap.read(frame);
      if (frame.empty())
      {
          waitKey();
          break;
      }

      vector<vector<int>> bboxes;
      Mat frameFace;
      tie(frameFace, bboxes) = getFaceBox(faceNet, frame, 0.7);

      if(bboxes.size() == 0) {
        cout << "No face detected, checking next frame." << endl;
        continue;
      }
      for (auto it = begin(bboxes); it != end(bboxes); ++it) {
        Rect rec(it->at(0) - padding, it->at(1) - padding, it->at(2) - it->at(0) + 2*padding, it->at(3) - it->at(1) + 2*padding);
        Mat face = frame(rec); // take the ROI of box on the frame

        Mat blob;
        blob = blobFromImage(face, 1, Size(227, 227), MODEL_MEAN_VALUES, false);
        genderNet.setInput(blob);
        // string gender_preds;
        vector<float> genderPreds = genderNet.forward();
        // printing gender here
        // find max element index
        // distance function does the argmax() work in C++
        int max_index_gender = std::distance(genderPreds.begin(), max_element(genderPreds.begin(), genderPreds.end()));
        string gender = genderList[max_index_gender];
        cout << "Gender: " << gender << endl;

        /* // Uncomment if you want to iterate through the gender_preds vector
        for(auto it=begin(gender_preds); it != end(gender_preds); ++it) {
          cout << *it << endl;
        }
        */

        ageNet.setInput(blob);
        vector<float> agePreds = ageNet.forward();
        /* // uncomment below code if you want to iterate through the age_preds
         * vector
        cout << "PRINTING AGE_PREDS" << endl;
        for(auto it = age_preds.begin(); it != age_preds.end(); ++it) {
          cout << *it << endl;
        }
        */

        // finding maximum indicd in the age_preds vector
        int max_indice_age = std::distance(agePreds.begin(), max_element(agePreds.begin(), agePreds.end()));
        string age = ageList[max_indice_age];
        cout << "Age: " << age << endl;
        string label = gender + ", " + age; // label
        cv::putText(frameFace, label, Point(it->at(0), it->at(1) -15), cv::FONT_HERSHEY_SIMPLEX, 0.9, Scalar(0, 255, 255), 2, cv::LINE_AA);
        imshow("Frame", frameFace);
        imwrite("out.jpg",frameFace);
      }

    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习深度学习——seq2seq实现机器翻译(数据集处理)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——从编码器-解码器架构到seq2seq&#xff08;机器翻译&#xff09; &#x1f4da;订阅专栏&#xff1a;机…

[数据集][目标检测]道路坑洼目标检测数据集VOC格式1510张2类别

数据集格式&#xff1a;Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件&#xff0c;仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数)&#xff1a;1510 标注数量(xml文件个数)&#xff1a;1510 标注类别数&#xff1a;2 标注类别名称:["keng","…

指针进阶大冒险:解锁C语言中的奇妙世界!

目录 引言 第一阶段&#xff1a;&#x1f50d; 独特的字符指针 什么是字符指针&#xff1f; 字符指针的用途 演示&#xff1a;使用字符指针拷贝字符串 字符指针与字符串常量 小试牛刀 第二阶段&#xff1a;&#x1f3af; 玩转指针数组 指针数组是什么&#xff1f; 指针…

操作系统—网络系统

什么是零拷贝 磁盘是计算机系统最慢的的硬件之一&#xff0c;所以有不少优化磁盘的方法&#xff0c;比如零拷贝、直接IO、异步IO等等&#xff0c;这些优化的目的是为了提高系统的吞吐量&#xff0c;另外操作系统内核中的磁盘高度缓存区&#xff0c;可以有效的减少磁盘的访问次…

HCIP---重发布技术

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 前文通过学习OSPF的不规则区域&#xff0c;了解了如何对不规则区域使用OSPF获取路由&…

JavaWeb-Servlet服务连接器(二)

目录 Request&#xff08;获取请求信息&#xff09; 1.获取请求行内容 2.解决乱码问题 3.获取请求头部分 4.获取请求体 5.其他功能 Request&#xff08;获取请求信息&#xff09; 工作流程&#xff1a; 1.通过请求的url的资源路径&#xff0c;tomcat会生成相应的Servlet实…

iOS 使用build setting中的配置项配置info.plist

如图所示&#xff0c;选中build setting&#xff0c;由于我们这里是想要获取版本号&#xff0c; 所以这里获取current project version 选中info&#xff0c;将bundle version 设置为$&#xff08;CURRENT_PROJECT_VERSION&#xff09;,注意&#xff0c;要使用下划线链接&…

【C++】常用容器-string容器

1.string基本概念 2.string构造函数 #include <iostream> using namespace std;//string容器 void test01() {string s1;//创建空字符串&#xff0c;调用无参构造函数cout << "str1 " << s1 << endl;//什么都不输出const char* str "…

阿里云服务器安装部署Docker使用教程

本文阿里云百科分享如何在云服务ECS实例上&#xff0c;部署并使用Docker。Docker是一款开源的应用容器引擎&#xff0c;具有可移植性、可扩展性、高安全性和可管理性等优势。开发者可将应用程序和依赖项打包到一个可移植的容器中&#xff0c;快速发布到Linux机器上并实现虚拟化…

react学习笔记——4. 虚拟dom中处理动态数据

如下需求 方式1&#xff1a; 直接在ul中使用{data}&#xff0c;是可以遍历数据的&#xff0c;然后如果将data改成下面形式&#xff0c;也是可以实现的。但是如果data是一个对象&#xff0c;则不能便利。 const data [<li>Angular</li>, <li>React</li&g…

c语言——统计分类

我们将一个班的成绩进行分类&#xff0c; 成绩60分以下的为c、成绩61-89分的为b&#xff0c;90分以上的为A //统计分类 /*我们将一个班的成绩进行分类&#xff0c; 成绩60分以下的为c、成绩61-89分的为b&#xff0c;90分以上的为A */ #include<stdio.h> int main() …

MyBatis的XML映射文件

Mybatis的开发有两种方式&#xff1a; 注解 XML配置文件 通过XML配置文件的形式来配置SQL语句&#xff0c;这份儿XML配置文件在MyBatis当中也称为XML映射文件。 导学&#xff1a;在MyBatis当中如何来定义一份儿XML映射文件&#xff1f; 在MyBatis当中&#xff0c;定义XML…

HCIP的BGP基础实验

一、实验需求 除R5的5.5.5.0环回外&#xff0c;其他所有的环回均可互相一访问。 二、实验步骤 1.配置ip 2.建立邻居关系 2.1 R1和R2建立直连的EBGP邻居关系 [r1]bgp 1 [r1-bgp]router-id 1.1.1.1 [r1-bgp]peer 12.1.1.2 as-number 2 要建的话双方都要建下面配置R2 [r2]bgp…

“冰箭卫士·IP发布会”首次亮相第14届海峡两岸(厦门)文博会

2023年8月6日,“冰箭卫士IP发布会”首次亮相海峡两岸文博会思明馆。此次发布会由厦门市文化创意产业协会、厦门理工&#xff08;集美区&#xff09;政产学研基地主办&#xff0c;厦门市文化创意产业协会IP设计研究院、厦门一笔之上文化发展有限公司、冰箭应急安全科技研究院承办…

springboot 设置自定义启动banner背景图 教程

springboot banner Spring Boot中的banner是在应用程序启动时显示的一个ASCII艺术字符或文本。它被用来给用户展示一些关于应用程序的信息&#xff0c;例如名称、版本号或者公司标志等。 使用Spring Boot的默认设置&#xff0c;如果项目中有一个名为“banner.txt”的文件放置…

交换排序——选择排序和冒泡排序的区别是什么?

今天重温一下算法&#xff0c;其实刚开始我觉得冒泡排序和选择排序是一样的&#xff0c;因为他们排序过程中都是通过相邻的数据比较找到最小/最大的数据&#xff0c;通过不断思考和学习才明白&#xff0c;两者还是有区别的。 冒泡排序 概念 冒泡排序(Bubble Sort)&#xff0…

【面试专题】Java核心基础篇①

&#x1f4c3;个人主页&#xff1a;个人主页 &#x1f525;系列专栏&#xff1a;Java面试专题 目录 1.面向对象的三大特性&#xff1f;分别解释下&#xff1f; 2.介绍一下Java的数据类型 3.说一说重写与重载的区别 4.说一说你对static关键字的理解 5.static修饰的类能不能…

ESP-01S Wi-Fi 模块:配置接线

ESP-01S Wi-Fi 模块&#xff1a;配置接线 参考&#xff1a;使用esp-01s与继电器配合实现远程开关灯 (zhihu.com) ESP-01S WiFi 模块 – 配置布线 - 技术探索 (techexplorations.com) 本文提供了将 ESP8266 Wi-Fi 模块与 Arduino Uno 配合使用的分步指南&#xff0c;重点介绍了…

湘大 XTU OJ 1291 Buying Gifts 题解(非常详细):枚举 维护最小值 排序

一、链接 1291 Buying Gifts 二、题目 题目描述 快到年末了&#xff0c;Boss Liu准备在年会上发些礼物&#xff0c;由于不想礼物的价格区别太大&#xff0c;Boss Liu希望最好的礼物与最差的礼物价格相差越小越好。 当然&#xff0c;如果存在相同的选择&#xff0c;Boss Liu…

python num循环怎么从1开始

如何实现python for循环从1开始&#xff1f; range()函数的作用和用法&#xff1a; 编写一个从数值1开始的循环&#xff1a; 执行后得到的结果 其他注意事项