深度神经网络加载 Caffe 框架模型

介绍

在本教程中,您将学习如何使用来自 Caffe 模型库的 GoogLeNet 训练网络opencv_dnn模块进行图像分类。

我们将在下图中演示此示例的结果。

space_shuttle.jpg

暴风雪号航天飞机

源代码

我们将使用示例应用程序中的片段,可以在此处下载。

​
#include < fstream>
#include < sstream>
#include < iostream>
#include < opencv2/dnn.hpp>
#include < opencv2/imgproc.hpp>
#include < opencv2/highgui.hpp>
#include“common.hpp”
std::string 键 =
“{ 帮助 h | |打印帮助消息。}"
“{ @alias | |用于从 models.yml 文件中提取预处理参数的模型别名。}"
“{ 动物园 |模型.yml |带有预处理参数的文件的可选路径 }”
“{ 输入 i | |输入图像或视频文件的路径。跳过此参数以从相机捕获帧。
“{ initial_width |0 |通过初始调整大小到特定宽度来预处理输入图像。
“{ initial_height |0 |通过初始调整大小到特定高度来预处理输入图像。
“{ std |0.0 0.0 0.0 |通过除以标准差对输入图像进行预处理。
“{ 裁剪 |假 |通过中心裁剪对输入图像进行预处理。
“{ 框架 f | |模型的原始框架的可选名称。如果未设置,则自动检测它。}"
“{ 需要Softmax |假 |使用 Softmax 对网络的输出进行后处理。
“{ 类 | |包含类名称的文本文件的可选路径。}"
“{ 后端 |0 |选择计算后端之一:”
“0:自动(默认),”
“1:卤化物语(http://halide-lang.org/), ”
“2:英特尔的深度学习推理引擎(https://software.intel.com/openvino-toolkit),
“3:OpenCV的实现,”
“4:VKCOM,”
“5:CUDA,”
“6:WebNN }”
“{ 目标 |0 |选择目标计算设备之一:”
“0:CPU 目标(默认)、”
“1:OpenCL,”
“2:OpenCL fp16(半浮点精度), ”
“3:VPU,”
“4:Vulkan,”
“6:CUDA,”
“7:CUDA fp16(半浮点预处理)}”;
使用命名空间 CV;
使用命名空间 DNN;
std::vector<std::string> 类;
int main(int argc, char** argv)
{
CommandLineParser 解析器(argc, argv, keys);
const std::string modelName = parser.get<String>(“@alias”);
const std::string zooFile = parser.get<String>(“zoo”);
键 += genPreprocArguments(modelName, zooFile);
解析器 = CommandLineParser(argc, argv, keys);
parser.about(“使用此脚本使用 OpenCV 运行分类深度学习网络。);
if (argc == 1 || parser.has(“帮助”))
{
解析器.printMessage();
返回 0;
}
int rszWidth = 解析器.get<int>(“initial_width”);
int rszHeight = 解析器.get<int>(“initial_height”);
浮点比例 = parser.get<float>(“scale”);
标量均值 = parser.get<Scalar>(“mean”);
标量标准 = parser.get<标量>(“标准”);
布尔交换RB = 解析器.get<布尔>(“rgb”);
bool 裁剪 = parser.get<bool>(“crop”);
int inpWidth = 解析器.get<int>(“宽度”);
int inpHeight = 解析器.get<int>(“高度”);
字符串模型 = findFile(parser.get<String>(“model”));
字符串配置 = findFile(parser.get<String>(“config”));
字符串框架 = parser.get<String>(“framework”);
int backendId = parser.get<int>(“后端”);
int targetId = 解析器.get<int>(“目标”);
bool needSoftmax = 解析器.get<bool>(“needSoftmax”);
std::cout<<“mean: ”<<mean<<std::endl;
std::cout<<“std: ”<<std<<std::endl;
打开带有类名称的文件。
if (parser.has(“类”))
{
std::string 文件 = parser.get<String>(“类”);
标准::ifstream ifs(file.c_str());
如果 (!ifs.is_open())
CV_Error(错误::StsError,“文件”+文件+“未找到”);
std::string 行;
而 (std::getline(ifs, line))
{
classes.push_back(线);
}
}
如果 (!parser.check())
{
解析器.printErrors();
返回 1;
}
CV_Assert(!model.empty());
Net net = readNet(model, config, framework);
net.setPreferableBackend(backendId);
net.setPreferableTarget(目标Id);
创建窗口
static const std::string kWinName = “OpenCV中的深度学习图像分类”;
namedWindow (kWinName, WINDOW_NORMAL);
VideoCapture 帽;
if (parser.has(“输入”))
帽。open(parser.get<String>(“输入”));
还
帽。打开(0);
处理帧。
垫框,斑点;
而 (waitKey(1) < 0)
{
帽>>框架;
如果 (frame.empty())
{
等待键();
破;
}
if (rszWidth != 0 && rszHeight != 0)
{
resize(frame, frame, Size(rszWidth, rszHeight));
}
blobFromImage(frame, blob, scale, Size(inpWidth, inpHeight), mean, swapRB, crop);
检查 std 值。
if (std.val[0] != 0.0 && std.val[1] != 0.0 && std.val[2] != 0.0)
{
将 blob 除以 std。
除法(blob, std, blob);
}
net.setInput(blob);
双t_sum = 0.0;
双T;
int 类 Id;
双重置信度;
cv::TickMeter 时间记录器;
timeRecorder。重置();
垫子概率 = net.forward();
双T1;
timeRecorder。开始();
prob = net.forward();
timeRecorder。停();
t1 = 时间记录器。getTimeMilli();
timeRecorder。重置();
for(int i = 0; i < 200; i++) {
timeRecorder。开始();
prob = net.forward();
timeRecorder。停();
点类IdPoint;
minMaxLoc(prob.reshape(1, 1), 0, &confidence, 0, &classIdPoint);
classId = classIdPoint。倍;
放置效率信息。
std::vector<double> layersTimes;
double freq = getTickFrequency() / 1000;
t = net.getPerfProfile(layersTimes) / freq;
t_sum += 吨;
}
如果 (needSoftmax == true)
{
浮点数 maxProb = 0.0;
浮点和 = 0.0;
垫子 softmaxProb;
maxProb = *std::max_element(prob.begin<float>(), prob.end<float>());
cv::exp(prob-maxProb, softmaxProb);
sum = (float)cv::sum(softmaxProb)[0];
softmaxProb /= 总和;
点类IdPoint;
minMaxLoc(softmaxProb.reshape(1, 1), 0, &confidence, 0, &classIdPoint);
classId = classIdPoint。倍;
}
std::string label = format(“1轮推理时间:%.2f ms”, t1);
std::string label2 = format(“200 轮的平均时间:%.2f ms”, timeRecorder.getTimeMilli()/200);
putText(frame, label, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0));
putText(frame, label2, Point(0, 35), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0));
打印预测的类。
label = format(“%s: %.4f”, (classes.empty() ?format(“类 #%d”, classId).c_str() :
类[classId].c_str()),
信心);
putText(frame, label, Point(0, 55), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0));
imshow(kWinName, 帧);
}
返回 0;
}
​

解释

  1. 首先,下载GoogLeNet模型文件:bvlc_googlenet.prototxtbvlc_googlenet.caffemodel

    此外,您还需要包含ILSVRC2012类名称的文件:classification_classes_ILSVRC2012.txt

    将这些文件放入此程序示例的工作目录中。

  2. 使用 .prototxt 和 .caffemodel 文件的路径读取和初始化网络
    Net net = readNet(model, config, framework);
    net.setPreferableBackend(backendId);
    net.setPreferableTarget(目标Id);
    如果其中一个文件或具有扩展名或 .这样,函数 cv::d nn::readNet 可以自动检测模型的格式。frameworkmodelconfig.caffemodel.prototxt
  3. 读取输入图像并转换为 blob,GoogleNet 可接受

    VideoCapture 帽;
    if (parser.has(“输入”))
    帽。open(parser.get<String>(“输入”));
    cap.open(0);

    cv::VideoCapture 可以加载图像和视频。

    bIobfromimage(frame, blob, scale, Size(inpWidth, inpHeight), mean, swapRB, crop);
    检查 std 值。
    if (std.val[0] != 0.0 && std.val[1] != 0.0 && std.val[2] != 0.0)
    {
    将 blob 除以 std。
    除法(blob, std, blob);
    }

    在使用 cv::d nn::blobFromImage 函数对每个蓝色、绿色和红色通道进行必要的预处理(如调整大小和均值减法)后,我们将图像转换为具有形状的 4 维斑点(所谓的批处理)。1x3x224x224(-104, -117, -123)

  4. 将 blob 传递到网络
    net.setInput(blob);
  5. 向前传球
    双t_sum = 0.0;
    双T;
    int 类 Id;
    双重置信度;
    cv::TickMeter 时间记录器;
    timeRecorder。重置();
    垫子概率 = net.forward();
    T1;
    timeRecorder。开始();
    prob = net.forward();
    timeRecorder。();
    t1 = 时间记录器。getTimeMilli();
    timeRecorder。重置();
    forint i = 0; i < 200; i++) {
    在前向传递期间,将计算每个网络层的输出,但在此示例中,我们只需要最后一层的输出。
  6. 确定最佳班级
    类IdPoint;
    minMaxLoc(prob.reshape(1, 1), 0, &confidence, 0, &classIdPoint);
    classId = classIdPoint.x;
    我们将网络的输出(包含 1000 个ILSVRC2012图像类中每个类的概率)放入 blob 中。并在此中找到具有最大值的元素的索引。此索引对应于图像的类。prob
  7. 从命令行运行示例
    ./example_dnn_classification --model=bvlc_googlenet.caffemodel --config=bvlc_googlenet.prototxt --width=224 --height=224 --classes=classification_classes_ILSVRC2012.txt --input=space_shuttle.jpg --mean=“104 117 123”
    对于我们的图像,我们得到了超过 99% 的确定性对类的预测。space shuttle

   在线教程

有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓

请添加图片描述

人工智能书籍

第一阶段:零基础入门(3-6个月)

新手应首先通过少而精的学习,看到全景图,建立大局观。 通过完成小实验,建立信心,才能避免“从入门到放弃”的尴尬。因此,第一阶段只推荐4本最必要的书(而且这些书到了第二、三阶段也能继续用),入门以后,在后续学习中再“哪里不会补哪里”即可。

第二阶段:基础进阶(3-6个月)

熟读《机器学习算法的数学解析与Python实现》并动手实践后,你已经对机器学习有了基本的了解,不再是小白了。这时可以开始触类旁通,学习热门技术,加强实践水平。在深入学习的同时,也可以探索自己感兴趣的方向,为求职面试打好基础。

第三阶段:工作应用

这一阶段你已经不再需要引导,只需要一些推荐书目。如果你从入门时就确认了未来的工作方向,可以在第二阶段就提前阅读相关入门书籍(对应“商业落地五大方向”中的前两本),然后再“哪里不会补哪里”。

 有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓

在这里插入图片描述

  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值