OpenCV4深度神经网络DNN实战教程

news/2024/9/19 0:54:16/ 标签: dnn, 人工智能, 神经网络, OpenCV

OpenCV4深度神经网络DNN实战教程

  • 1-概述与环境配置
  • 2-卷积神经网络概述
  • 3-加载网络模型与设置
    • 3.1 所需的模型下载
    • 3.2 所使用的模型(googlenet)
    • 3.3 Net介绍
    • 3.4 代码输出网络结构信息
    • 3.5 计算后台设置
    • 3.6 所有代码
  • 4-图像分类网络inception的使用
  • 5-读取分类标签文件显示分类
  • 6-对象检测网络介绍
  • 7-SSD对象检测网络加载与执行
  • 8-SSD对象检测推理输出解释与显示
  • 9-Faster RCNN对象检测模型使用
    • 解决无法打开RAW的问题
  • 10-YOLOv3对象检测模型推理使用
  • 11-OpenCV DNN配置加速组件IE支持

1-概述与环境配置

OpenCV DNN模块
传统的HAAR级联人脸检测器不可靠到DNN的高可靠

各种操作
,如何将TensorFlow训练出来的模型导入到,实现很好的调用

OpenCVDNN模块可以解决

OpenCV4不再是单纯的计算机视觉库,还有深度学习推理库
OpenCV4后与神经网络

扩展模块
在3.3中放到了release版本中

旧的教程下线有瑕疵
此时已经很成熟了,通过IE加速(推理引擎,7、8倍的效率提升)
OpenCV4模型数很多

OpenCVgithub官方网站https://github.com/opencv/opencv
点击wiki
https://github.com/opencv/opencv/wiki/Deep-Learning-in-OpenCV
有很多关于深度学习的介绍

OpenCV face detector已经做的非常好了,模型只有几兆,但检测,完全可以抛弃级联检测方式

整个目录围绕模型展开。
在这里插入图片描述

色彩,风格迁移

OpenCV 的DNN如何使用,在应用层
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2-卷积神经网络概述

如何还用OpenCV的API加载神经网络各个层次
卷积神经网络框架中,有paddle填充模式,sim是输入3232大小,输出还是3232大小。而value输入3232,输出则变为2828.。

重叠池化的步长永远是1

局部池化,步长是其大小

最大值池化、均值池化,根据数据
在这里插入图片描述

3-加载网络模型与设置

https://www.pianshen.com/article/9895277588/
在这里插入图片描述

如何加载一个网络,网络有输入,输入是图像,c通道数,h高度,w宽度,N一般为1,表示1张图像的预测,也可以多张图像

获取输出层有个api
在这里插入图片描述

3.1 所需的模型下载

opencv_tutorial-master文件是从Google下载的,下载路径为实际上下载的东西在贾老师的GitHub上就有,
https://github.com/gloomyfish1998/opencv_tutorial/
将下载好的文件保存在了D:\OpenCV\project\下

3.2 所使用的模型(googlenet)

D:\OpenCV\project\opencv_tutorial-master\data\models\googlenet
在这里插入图片描述

bvlc_googlenet.caffemodel这是个caffe模型,在OpenCV中支持离线加载,不依赖caffe,这是模型的权重文件
bvlc_googlenet.prototxt这是模型的描述文件
Imagenet支持1000个分类,分类类别在classification_classes_ILSVRC2012.txt可以看到,使用editplus可以看到一直到1000行
//有了模型的权重和描述文件就可以加载模型了

3.3 Net介绍

(1)在OpenCV中加载模型要通过readNetWork函数
(2)readNet函数有三个参数,参数1加载网络(caffe、TensorFlow等),参数2,3为权重路径和描述文件
(3)或者readNetFromCaffe(TensorFlow、darknet、ONNX等),意思为读进来的必须是caffe模型,此外还支持TensorFlow等模型,只有两个参数
(4)还有readNetFromModelOptimizer从dnn模型优化器中读取模型优化后的模型

Net net = readNetFromCaffe(protxt, bin_model);	//此处只能加载caffe的

3.4 代码输出网络结构信息

#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>			//包含dnn模块的头文件
#include <iostream>using namespace cv;
using namespace cv::dnn;			//包含dnn的命名空间
using namespace std;int main() {string bin_model = "D:/OpenCV/project/opencv_tutorial-master/data/models/googlenet/bvlc_googlenet.caffemodel";		//定义模型权重文件的加载路径string protxt = "D:/OpenCV/project/opencv_tutorial-master/data/models/googlenet/bvlc_googlenet.prototxt";			//定义模型描述文件的加载路径//Imagenet支持1000个分类,分类类别在classification_classes_ILSVRC2012.txt可以看到,一直到1000//有了模型的权重和描述文件就可以加载模型了//在OpenCV中加载模型要通过readNetWork,//readNet函数有三个参数,参数1加载网络(caffe、TensorFlow等),参数2,权重路径,参数3,描述文件//或者readNetFromCaffe(TensorFlow、darknet、ONNX等),意思为读进来的必须是caffe模型,此外还支持TensorFlow等模型,只有两个参数//还有readNetFromModelOptimizer从dnn模型优化器中读取模型优化后的模型Net net = readNetFromCaffe(protxt, bin_model);vector<string> layer_names = net.getLayerNames();		//此时我们就可以获取所有层的名称了,有了这些可以将其ID取出for (int i = 0; i < layer_names.size(); i++) {int id = net.getLayerId(layer_names[i]);			//通过name获取其idauto layer = net.getLayer(id);						//通过id获取layerprintf("layer id:%d,type:%s,name:%s\n", id, layer->type.c_str(), layer->name.c_str());	//将每一层的id,类型,姓名打印出来(可以明白此网络有哪些结构信息了)}waitKey(0);return 0;
}

在这里插入图片描述
在这里插入图片描述

我们知道这个网络有142层,Convolution卷积层,relu激活函数,pooling池化层,此时就搞清楚网络结构了

现在去搞其他的网络的层等信息也就清楚了

3.5 计算后台设置

//设置计算后台(OpenCVdnn模块支持设置不同的计算后台和在不同的设备上进行)net.setPreferableBackend(DNN_BACKEND_OPENCV);				//setPreferableBackend实际计算后台,default默认是DNN_BACKEND_OPENCV作为计算后台,使用此就行(也有加速后台ENGINE)net.setPreferableTarget(DNN_TARGET_CPU);						//设置在什么设备上进行计算(opencl(需要有interl图形卡)、FPGA、CPU)//当上面两个设置之后,他在执行网络进行推算时就会执行此计算后台进行计算(不同的计算后台有不同的效果,速度也有差别)

本节课学习了如何加载一个网络,此网络是Googlenet的,下节会讲如何使用此网络实现图像的分类预测

3.6 所有代码

#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>			//包含dnn模块的头文件
#include <iostream>using namespace cv;
using namespace cv::dnn;			//包含dnn的命名空间
using namespace std;int main() {string bin_model = "D:/OpenCV/project/opencv_tutorial-master/data/models/googlenet/bvlc_googlenet.caffemodel";		//定义模型权重文件的加载路径string protxt = "D:/OpenCV/project/opencv_tutorial-master/data/models/googlenet/bvlc_googlenet.prototxt";			//定义模型描述文件的加载路径//Imagenet支持1000个分类,分类类别在classification_classes_ILSVRC2012.txt可以看到,一直到1000//有了模型的权重和描述文件就可以加载模型了//在OpenCV中加载模型要通过readNetWork,//readNet函数有三个参数,参数1加载网络(caffe、TensorFlow等),参数2,权重路径,参数3,描述文件//或者readNetFromCaffe(TensorFlow、darknet、ONNX等),意思为读进来的必须是caffe模型,此外还支持TensorFlow等模型,只有两个参数//还有readNetFromModelOptimizer从dnn模型优化器中读取模型优化后的模型Net net = readNetFromCaffe(protxt, bin_model);//设置计算后台(OpenCVdnn模块支持设置不同的计算后台和在不同的设备上进行)net.setPreferableBackend(DNN_BACKEND_OPENCV);				//setPreferableBackend实际计算后台,default默认是DNN_BACKEND_OPENCV作为计算后台,使用此就行(也有加速后台ENGINE)net.setPreferableTarget(DNN_TARGET_CPU);						//设置在什么设备上进行计算(opencl(需要有interl图形卡)、FPGA、CPU)//当上面两个设置之后,他在执行网络进行推算时就会执行此计算后台进行计算(不同的计算后台有不同的效果,速度也有差别)//获取各层信息vector<string> layer_names = net.getLayerNames();		//此时我们就可以获取所有层的名称了,有了这些可以将其ID取出for (int i = 0; i < layer_names.size(); i++) {int id = net.getLayerId(layer_names[i]);			//通过name获取其idauto layer = net.getLayer(id);						//通过id获取layerprintf("layer id:%d,type:%s,name:%s\n", id, layer->type.c_str(), layer->name.c_str());	//将每一层的id,类型,姓名打印出来(可以明白此网络有哪些结构信息了)}waitKey(0);return 0;
}

4-图像分类网络inception的使用

池化层降维,卷积层提取特征,
利用已经训练好的模型在OpenCV中进行离线的调用

之前加载caffe模型,各个层次读取
图像分类识别
在这里插入图片描述
在这里插入图片描述

此图像分类模型主要来自谷歌,在CVPR2015发表
与之前的相比发表了inception模型

此模型可以对1000个类别进行分类
在这里插入图片描述

OpenCV官方网站有关于模型中通道是BGR还是RGB的说明
https://github.com/opencv/opencv/wiki/Deep-Learning-in-OpenCV

https://github.com/opencv/opencv/blob/master/samples/dnn/models.yml
有个配置文件,配置说明文件,就说了各个模型调用的时候有哪些需要输入的参数。通过此模型给出的参数 进行设置

Googlenet是RGB的通道顺序
最后一层是softmax
基于imagenet数据集的
它的类有
D:\OpenCV\project\opencv_tutorial-master\data\models\googlenet中的
classification_classes_ILSVRC2012.txt

构建输入可以参考OpenCV自带的配置文件,根据此文件进行构建输入
D:\OpenCV\opencv-4.4.0-vc14_vc15\opencv\sources\samples\dnn\models.yml
打开文件可以看到,上方链接为模型的下载链接,下方参数为构建输入,进行图像预处理时的参数
在这里插入图片描述

当我们需要继续对其分类时

#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>			//包含dnn模块的头文件
#include <iostream>using namespace cv;
using namespace cv::dnn;			//包含dnn的命名空间
using namespace std;int main() {string bin_model = "D:/OpenCV/project/opencv_tutorial-master/data/models/googlenet/bvlc_googlenet.caffemodel";		//定义模型权重文件的加载路径string protxt = "D:/OpenCV/project/opencv_tutorial-master/data/models/googlenet/bvlc_googlenet.prototxt";			//定义模型描述文件的加载路径//Imagenet支持1000个分类,分类类别在classification_classes_ILSVRC2012.txt可以看到,一直到1000//有了模型的权重和描述文件就可以加载模型了//在OpenCV中加载模型要通过readNetWork,//readNet函数有三个参数,参数1加载网络(caffe、TensorFlow等),参数2,权重路径,参数3,描述文件//或者readNetFromCaffe(TensorFlow、darknet、ONNX等),意思为读进来的必须是caffe模型,此外还支持TensorFlow等模型,只有两个参数//还有readNetFromModelOptimizer从dnn模型优化器中读取模型优化后的模型Net net = readNetFromCaffe(protxt, bin_model);//设置计算后台(OpenCVdnn模块支持设置不同的计算后台和在不同的设备上进行)net.setPreferableBackend(DNN_BACKEND_OPENCV);				//setPreferableBackend实际计算后台,default默认是DNN_BACKEND_OPENCV作为计算后台,使用此就行(也有加速后台ENGINE)net.setPreferableTarget(DNN_TARGET_CPU);						//设置在什么设备上进行计算(opencl(需要有interl图形卡)、FPGA、CPU)//当上面两个设置之后,他在执行网络进行推算时就会执行此计算后台进行计算(不同的计算后台有不同的效果,速度也有差别)//获取各层信息vector<string> layer_names = net.getLayerNames();		//此时我们就可以获取所有层的名称了,有了这些可以将其ID取出for (int i = 0; i < layer_names.size(); i++) {int id = net.getLayerId(layer_names[i]);			//通过name获取其idauto layer = net.getLayer(id);						//通过id获取layerprintf("layer id:%d,type:%s,name:%s\n", id, layer->type.c_str(), layer->name.c_str());	//将每一层的id,类型,姓名打印出来(可以明白此网络有哪些结构信息了)//printf("name2:%s\n", layer_names[i].c_str());}Mat src = imread("G:/OpenCV/opencv笔记所用图片/plane.jpg");imshow("src", src);因为googlenet的通道类型是RGB通道的,而OpenCVread读取的是BGR通道的,要进行通道转换(实际在后面的blobFromImage就能进行通道转换,此处无需转换)//Mat rgb;	//cvtColor(src, rgb, COLOR_BGR2RGB);//构建输入//使用blobFromImage函数对单张图像进行预处理,使其符合网络的输入//对于网络来说原始输入层的时候都有指定的输入大小int w = 224;int h = 224;
Mat inputBlob = blobFromImage(src, 1.0, Size(w, h),Scalar(104, 117, 123), false,false);	//我们要将图像resize成224*224的才是我们神经网络可以接受的宽高//参数1:输入图像,参数2:默认1.0表示0-255范围的,参数3:设置输出的大小,参数4:均值对所有数据中心化预处理,参数5:是否进行通道转换,参数6:,参数7:默认深度为浮点型//设置输入//前面已经将图像预处理完成,就可以执行分类了//现在要将其输入到创建的网络中net.setInput(inputBlob);//进行推断得到输出//让网络执行得到output,调用forward可以得到一个结果//此处不给参数,得到的是最后一层的结果,也可以输入层数得到任何一层的输出结果Mat probMat = net.forward();	//通过前面的输出层看最后一层,可以知道输出100个分类,每个分类的得分是多少//softmax层出来的总和为1,找到max值对应的index就知道对应的分类了,在classification_classes_ILSVRC2012.txt可以知道具体名称//上方得到的probMat是1000*1*1(有imagewatch得到)//要解析输出(forward得到的)//对数据进行序列化(变成1行n列的,可以在后面进行方便的知道是哪个index了)Mat prob = probMat.reshape(1, 1);		//reshape函数可以进行序列化,(输出为1通道1行的数据,参数1:1个通道,参数2:1行)将输出结果变成1行n列的,但前面probMat本身就是1000*1*1//实际结果probMat和prob相同//当其他网络probMat需要序列化的时候,reshape就可以了//此时找到最大的那个Point classNum;double classProb;minMaxLoc(prob, NULL, &classProb, NULL, &classNum);//此时只获取最大值及最大值位置,最小值不管他int index = classNum.x;		//此时得到的是最大值的列坐标。就是其类的索引值,就可以知道其类名了printf("\n current index=%d,possible:%2f\n",index,classProb);	// current index=812,possible:0.999675,用editplus打开classification_classes_ILSVRC2012.txt,找到第813行(因为812+1)就是结果//这样自己在classification_classes_ILSVRC2012.txt找答案挺麻烦的,我们使用程序打开此文件,得到类名即可waitKey(0);return 0;
}

5-读取分类标签文件显示分类

一般对于自然场景的图像可以进行较精确的分类,利于后期图像查找等

输出层解析:主要讲其变为我们能接收的对象,找出最大可能性及其对于index
标签匹配:读入txt文件使其与index一一对应,最终得到类名

#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>			//包含dnn模块的头文件
#include <iostream>
#include <fstream>				//文件流进行txt文件读取using namespace cv;
using namespace cv::dnn;			//包含dnn的命名空间
using namespace std;vector<string> readLabels();		//将类名的txt文件读取到容器中int main() {string bin_model = "D:/OpenCV/project/opencv_tutorial-master/data/models/googlenet/bvlc_googlenet.caffemodel";		//定义模型权重文件的加载路径string protxt = "D:/OpenCV/project/opencv_tutorial-master/data/models/googlenet/bvlc_googlenet.prototxt";			//定义模型描述文件的加载路径//Imagenet支持1000个分类,分类类别在classification_classes_ILSVRC2012.txt可以看到,一直到1000vector<string> names = readLabels();		//使用自定义函数读取特定文件中的类名到names中,在后面输出对应名称时会用到//有了模型的权重和描述文件就可以加载模型了//在OpenCV中加载模型要通过readNetWork,//readNet函数有三个参数,参数1加载网络(caffe、TensorFlow等),参数2,权重路径,参数3,描述文件//或者readNetFromCaffe(TensorFlow、darknet、ONNX等),意思为读进来的必须是caffe模型,此外还支持TensorFlow等模型,只有两个参数//还有readNetFromModelOptimizer从dnn模型优化器中读取模型优化后的模型Net net = readNetFromCaffe(protxt, bin_model);//设置计算后台(OpenCVdnn模块支持设置不同的计算后台和在不同的设备上进行)net.setPreferableBackend(DNN_BACKEND_OPENCV);				//setPreferableBackend实际计算后台,default默认是DNN_BACKEND_OPENCV作为计算后台,使用此就行(也有加速后台ENGINE)net.setPreferableTarget(DNN_TARGET_CPU);						//设置在什么设备上进行计算(opencl(需要有interl图形卡)、FPGA、CPU)//当上面两个设置之后,他在执行网络进行推算时就会执行此计算后台进行计算(不同的计算后台有不同的效果,速度也有差别)//获取各层信息vector<string> layer_names = net.getLayerNames();		//此时我们就可以获取所有层的名称了,有了这些可以将其ID取出for (int i = 0; i < layer_names.size(); i++) {int id = net.getLayerId(layer_names[i]);			//通过name获取其idauto layer = net.getLayer(id);						//通过id获取layerprintf("layer id:%d,type:%s,name:%s\n", id, layer->type.c_str(), layer->name.c_str());	//将每一层的id,类型,姓名打印出来(可以明白此网络有哪些结构信息了)//printf("name2:%s\n", layer_names[i].c_str());}Mat src = imread("G:/OpenCV/opencv笔记所用图片/plane.jpg");imshow("src", src);因为googlenet的通道类型是RGB通道的,而OpenCVread读取的是BGR通道的,要进行通道转换(实际在后面的blobFromImage就能进行通道转换,此处无需转换)//Mat rgb;	//cvtColor(src, rgb, COLOR_BGR2RGB);//构建输入//使用blobFromImage函数对单张图像进行预处理,使其符合网络的输入//对于网络来说原始输入层的时候都有指定的输入大小int w = 224;int h = 224;Mat inputBlob = blobFromImage(src, 1.0, Size(w, h),Scalar(104, 117, 123), false,false);	//我们要将图像resize成224*224的才是我们神经网络可以接受的宽高//参数1:输入图像,参数2:默认1.0表示0-255范围的,参数3:设置输出的大小,参数4:均值对所有数据中心化预处理,参数5:是否进行通道转换,参数6:,参数7:默认深度为浮点型//设置输入//前面已经将图像预处理完成,就可以执行分类了//现在要将其输入到创建的网络中net.setInput(inputBlob);//进行推断得到输出//让网络执行得到output,调用forward可以得到一个结果//此处不给参数,得到的是最后一层的结果,也可以输入层数得到任何一层的输出结果Mat probMat = net.forward();	//通过前面的输出层看最后一层,可以知道输出100个分类,每个分类的得分是多少//softmax层出来的总和为1,找到max值对应的index就知道对应的分类了,在classification_classes_ILSVRC2012.txt可以知道具体名称//上方得到的probMat是1000*1*1(有imagewatch得到)//要解析输出(forward得到的)//对数据进行序列化(变成1行n列的,可以在后面进行方便的知道是哪个index了)Mat prob = probMat.reshape(1, 1);		//reshape函数可以进行序列化,(输出为1通道1行的数据,参数1:1个通道,参数2:1行)将输出结果变成1行n列的,但前面probMat本身就是1000*1*1//实际结果probMat和prob相同//当其他网络probMat需要序列化的时候,reshape就可以了//此时找到最大的那个Point classNum;double classProb;minMaxLoc(prob, NULL, &classProb, NULL, &classNum);//此时只获取最大值及最大值位置,最小值不管他int index = classNum.x;		//此时得到的是最大值的列坐标。就是其类的索引值,就可以知道其类名了printf("\n current index=%d,possible:%2f,name=%s\n",index,classProb,names[index].c_str());	// current index=812,possible:0.999675,用editplus打开classification_classes_ILSVRC2012.txt,找到第813行(因为812+1)就是结果//这样自己在classification_classes_ILSVRC2012.txt找答案挺麻烦的,我们使用程序打开此文件,得到类名即可//此时可以将名称打印到图片上去putText(src, names[index].c_str(), Point(50, 50), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 255), 2, 8);imshow("result", src);waitKey(0);return 0;
}vector<string> readLabels() {string label_map_txt = "D:/OpenCV/project/opencv_tutorial-master/data/models/googlenet/classification_classes_ILSVRC2012.txt";vector<string> classNames;ifstream fp(label_map_txt);if (!fp.is_open()) {printf("could not find the file \n");exit(-1);}std::string name;while (!fp.eof()) {		//当没有结束时就一直读取getline(fp, name);	//每次读取一行if (name.length()) {classNames.push_back(name);}}fp.close();		//关闭文件输入流return classNames;
}

6-对象检测网络介绍

前面学习了如何通过DNN实现图像的分类,
图像分类的预训练模型googlenet,哪些层,输入,输出哪些看到
怎么去set到网络中,forward得到输出,可以forward任意一层,默认最后一层

对网络进行加载,相关后台设备,网络分类。

OpenCV的DNN模块只能进行推理,不能执行训练,训练是有各个深度学习的框架完成的,
这节课学习对象检测模型。

在计算机视觉中对象检测,常见模型及其输出层格式不同。

对象检测模型进行应用的代码演示。
在这里插入图片描述

前面的是分类,现在要检测:

图像的分类加对象位置信息就是对象检测
在这里插入图片描述

前面的googlenet只是得到分类信息就可以了

而检测还需要得到位置信息,长宽高等位置,得到位置信息再进行矩形
Image classification 图像分类
Object detection 对象检测
在这里插入图片描述

这些模型都有一些结构性的不同
在这里插入图片描述

卷积提取特征,RPN区域推荐网络,输出会产生很多ROI区域,可以对ROI区域分类,有了分类信息和位置信息

RCNN分类,位置回归,对象在什么位置,可能性是多少
在这里插入图片描述
在这里插入图片描述

SSD缺点,如果目标太小就检测不到了,对小物体检测效果不太好。

非最大抑制,可能会在不同的层次匹配到对象
在这里插入图片描述

SSD全是卷积的神经网络,训练,速度快,很多时候使用

YOLO也慢慢变成全卷积的网络了
在这里插入图片描述

Scale都是有阈值的,大于0.5的保留,小于的去掉

YOLOV3多尺度输出
在这里插入图片描述

YOLOV3输出的是其中心位置和宽高,解析方式与faster RCNN不同
在这里插入图片描述

YOLO最后一层的输出方式
11N7 N是多少张图,7个值,1,bumbox,index,scale,4个位置信息
1
1N(5+score) 矩形信息和得分

不同网络最后一层输出方式不同,代码使用也不同

7-SSD对象检测网络加载与执行

SSD一次就能检测出多个box
SSD基础网络不一样,导出权重大小不一样的离线模型文件
在这里插入图片描述

数据集都是室内常见的物体,书,车,人,狗等类别

得分越高,在此数据集的表现越好
在这里插入图片描述

Scale是2/255

上面是模型的相关介绍
在这里插入图片描述

推断预测,结果解析,
data就是参数层的名称

CV_WRAP void setInput(InputArray blob, const String& name = "",double scalefactor = 1.0, const Scalar& mean = Scalar());/** @brief Sets the new value for the learned param of the layer.*  @param layer name or id of the layer.*  @param numParam index of the layer parameter in the Layer::blobs array.*  @param blob the new value.*  @see Layer::blobs*  @note If shape of the new blob differs from the previous shape,*  then the following forward pass may fail.*/

Forward 最终输出层就是detection_out
detection_out这一层出来的就是117的

D:\OpenCV\opencv-4.4.0-vc14_vc15\opencv\sources\samples\dnn在其下方的moduls.yml文件中有关于各个模型的参数配置,
在这里插入图片描述
在这里插入图片描述

而其labelmap_det.txt文件中内容有点多,实际可以总结出
如下

String objNames[] = { "background",
"aeroplane","bicycle","bird","boat",
"bottle","bus","car","cat","chair",
"cow","diningtable","dog","horse",
"motorbike","person","pottedplant",
"sheep","sofa","train","tvmonitor" };

输入层就是data

获取的层信息发现,最后一层就是detection_out

在这里插入图片描述
在这里插入图片描述

8-SSD对象检测推理输出解释与显示

加载输入,解析输出,后面会有针对视频的对象检测

#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>			//包含dnn模块的头文件
#include <iostream>
#include <fstream>				//文件流进行txt文件读取using namespace cv;
using namespace cv::dnn;			//包含dnn的命名空间
using namespace std;String objNames[] = { "background",
"aeroplane","bicycle","bird","boat",
"bottle","bus","car","cat","chair",
"cow","diningtable","dog","horse",
"motorbike","person","pottedplant",
"sheep","sofa","train","tvmonitor" };int main() {string bin_model = "D:/OpenCV/project/opencv_tutorial-master/data/models/ssd/MobileNetSSD_deploy.caffemodel";		//定义模型权重文件的加载路径string protxt = "D:/OpenCV/project/opencv_tutorial-master/data/models/ssd/MobileNetSSD_deploy.prototxt";			//定义模型描述文件的加载路径//load DNN modelNet net = readNetFromCaffe(protxt, bin_model);//设置计算后台(OpenCVdnn模块支持设置不同的计算后台和在不同的设备上进行)net.setPreferableBackend(DNN_BACKEND_OPENCV);				//setPreferableBackend实际计算后台,default默认是DNN_BACKEND_OPENCV作为计算后台,使用此就行(也有加速后台ENGINE)net.setPreferableTarget(DNN_TARGET_CPU);						//设置在什么设备上进行计算(opencl(需要有interl图形卡)、FPGA、CPU)//获取各层信息vector<string> layer_names = net.getLayerNames();		//此时我们就可以获取所有层的名称了,有了这些可以将其ID取出for (int i = 0; i < layer_names.size(); i++) {int id = net.getLayerId(layer_names[i]);			//通过name获取其idauto layer = net.getLayer(id);						//通过id获取layerprintf("layer id:%d,type:%s,name:%s\n", id, layer->type.c_str(), layer->name.c_str());	//将每一层的id,类型,姓名打印出来(可以明白此网络有哪些结构信息了)}Mat src = imread("G:/OpenCV/opencv笔记所用图片/gou.jpg");	//planeif (src.empty()) {cout << "could not load image.." << endl;getchar();return -1;}imshow("src", src);//构建输入(根据models.yml)Mat blob = blobFromImage(src, 0.007843, Size(300, 300), Scalar(127.5, 127.5, 127.5), false, false);	//交换通道false,是否剪切falsenet.setInput(blob, "data");		//输入层名称就是data,通过描述文件也可以看到输入层名称//推测结果Mat detection = net.forward("detection_out");	//将名称为detection_out的层的结果返回,不输入名称默认也是返回最后一层,输入可以返回特定层的结果//上方得到的detection宽高为0(使用imagewatch查看,原因是其为tensen,它的宽高维度等信息都存在size结构中,所以要在下方通过size获取)//重新定义一个Mat对象接收Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());		//此处是初始化一个行为size[2],列为size[3]大小,深度为浮点型,数据从detection中获取//使用imagewatch可以看到7*100的数组,单通道32F深度//获取浮点型数据后就可以进行数据的解析了float confidence_threshold = 0.5;		//在后面通过此判断合适的结果进行保存//解析输出数据//上方获取的detectionMat是100行,7列的,每行对应一个对象//输出结果[1x1xNx7], 其中输出的七个维度浮点数如下://[image_id, label, conf, x_min, y_min, x_max, y_max]for (int i = 0; i < detectionMat.rows; i++) {float score = detectionMat.at<float>(i, 2);			//此处获取的是conf(i, 2),也就是得分if (score > confidence_threshold) {					//如果获取的score大于0.5,就将box保存,不要扔掉size_t objIndex = (size_t)(detectionMat.at<float>(i, 1));		//此处获取的是label(i, 2),就是索引//得到四个点的矩形框位置float tl_x = detectionMat.at<float>(i, 3)*src.cols;		//x_min(此处detectionMat.at<float>(i, 3)得到的是一个图像的比例值不是真实值,需要变换)float tl_y = detectionMat.at<float>(i, 4)*src.rows;		//y_minfloat br_x = detectionMat.at<float>(i, 5)*src.cols;		//x_maxfloat br_y = detectionMat.at<float>(i, 6)*src.rows;		//y_max//得到boxRect box((int)tl_x, (int)tl_y, (int)br_x - tl_x, (int)br_y - tl_y);//画矩形rectangle(src, box, Scalar(0, 0, 255), 2, 8, 0);//写文字(在box的做上角写文字)putText(src, format("score:%2f,%s",score,objNames[objIndex].c_str()), box.tl(), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(255, 0, 0), 2, 8);}}imshow("ssd-detection-demo", src);waitKey(0);return 0;
}

9-Faster RCNN对象检测模型使用

前面是SSD对象检测网络实现离线运行进行检测

加载模型,推理,输出,解析,输出格式是11N*7
至于网络中间部分训练时会关心,而推测评估时,只需知道输入输出,解析输出结果即可,
也可以获取卷积各层信息

Faster-RCNN是TensorFlow对象检测,TensorFlow object API

怎么将TensorFlow支持的对象拿出来
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一定不要将其拷贝代码

将下载的描述文件复制到此文件目录下
在这里插入图片描述

上面的很多网络都是来自TensorFlow的预训练框架,已经训练好了,只需要将其权重及描述文件下载下来即可离线使用
点击进入,点击row另存为,不要拷贝会破坏格式。

本处下载的是faster-RCNN resnet50的权重文件及配置文件

下载的配置文件,后缀会有.txt, 重命名将多余的.txt删除

解决无法打开RAW的问题

Windows上可以这样办:
上https://www.ipaddress.com查一下raw.githubusercontent.com的ipv4地址,比如我现在查到的是199.232.68.133。
使用管理员权限打开C:\Windows\System32\drivers\etc\hosts文件,添加到最后一行

199.232.68.133 raw.githubusercontent.com 

或者管理员权限开或者给个用户写入权限。然后差不多就行了,可能要重启。不过本人使用editplus将其打开并输入后再打开raw.githubusercontent.com就成功了。
在这里插入图片描述

D:\OpenCV\project\opencv_tutorial-master\data\models\mscoco_label_map.pbtxt
数据集的类名有80个,在上面的文件内

80个类别定义数组太麻烦,直接采用读取读取.pbtxt文件的方式将类名导入进来
在这里插入图片描述

上面的格式
在这里插入图片描述

D:\OpenCV\project\opencv_tutorial-master\data\models\TensorFlow\faster_rcnn_resnet50_coco_2018_01_28
frozen_inference_graph.pb
faster_rcnn_resnet50_coco_2018_01_28.pbtxt

在这里插入图片描述

有时检测对象不多,将confidence值调低一些如0.5变为0.3如下所示可以检测出(但可能有些出错,一般以0.5即可)
在这里插入图片描述

此网络模型要比SSD耗时多

10-YOLOv3对象检测模型推理使用

Faster-RCNN来自TensorFlow的object detection即对象检测框架,此框架也有其他的对象检测网络,可以也被OpenCV4的DNN模块接收,并且数据设置与faster-RCNN类似

SSD来自caffe
Faster-RCNN来自TensorFlow
YOLO来自darknet框架,是C语言的框架,主要为YOLO服务
在这里插入图片描述

COCO数据集支持80个分类
常用的物体基本在其内

配置文件与权重
https://pjreddie.com/darknet/yolo/
在这里插入图片描述

YOLOV3-416 表示宽高416

YOLO有多个输出层,不像faster-RCNN、SSD只有一个输出层

YOLO有多个输出层,在这个层发现,另一个层也发现了,需要调用NMS将所有输出层结果合并
在这里插入图片描述
在这里插入图片描述

输出
NMS去掉重复box
Yolo有几个输出层,可能在好几个层都检测到了然后输出

NMS
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>			//包含dnn模块的头文件
#include <iostream>
#include <fstream>				//文件流进行txt文件读取using namespace cv;
using namespace cv::dnn;			//包含dnn的命名空间
using namespace std;string label_map = "D:/OpenCV/project/opencv_tutorial-master/data/models/YOLO3/object_detection_classes_yolov3.txt";int main() {string weight_file = "D:/OpenCV/project/opencv_tutorial-master/data/models/YOLO3/yolov3.weights";		//定义模型权重文件的加载路径string cfg_file = "D:/OpenCV/project/opencv_tutorial-master/data/models/YOLO3/yolov3.cfg";			//定义模型描述文件的加载路径//load DNN modelNet net = readNetFromDarknet(cfg_file, weight_file);vector<String> outNames = net.getUnconnectedOutLayersNames();	//获取多个输出层for (int k = 0; k < outNames.size(); k++) {printf("output layer name:%s \n", outNames[k].c_str());}//设置计算后台(OpenCVdnn模块支持设置不同的计算后台和在不同的设备上进行)net.setPreferableBackend(DNN_BACKEND_OPENCV);				//setPreferableBackend实际计算后台,default默认是DNN_BACKEND_OPENCV作为计算后台,使用此就行(也有加速后台ENGINE)net.setPreferableTarget(DNN_TARGET_CPU);						//设置在什么设备上进行计算(opencl(需要有interl图形卡)、FPGA、CPU)//获取各层信息vector<string> layer_names = net.getLayerNames();		//此时我们就可以获取所有层的名称了,有了这些可以将其ID取出for (int i = 0; i < layer_names.size(); i++) {int id = net.getLayerId(layer_names[i]);			//通过name获取其idauto layer = net.getLayer(id);						//通过id获取layerprintf("layer id:%d,type:%s,name:%s\n", id, layer->type.c_str(), layer->name.c_str());	//将每一层的id,类型,姓名打印出来(可以明白此网络有哪些结构信息了)}Mat src = imread("G:/OpenCV/opencv笔记所用图片/gou.jpg");	//planeif (src.empty()) {cout << "could not load image.." << endl;getchar();return -1;}imshow("src", src);Mat blob = blobFromImage(src, 0.00392, Size(416, 416), Scalar(), true, false);net.setInput(blob);//推理输出vector<Mat> outs;net.forward(outs, layer_names);	//将三个输出层的结果都得到vector<Rect> boxes;		//三个输出层的box信息接收vector<int> classIds;	//接收三个类的信息vector<float> confidences;	//接收三个得分信息for (int i = 0; i < outs.size(); i++) {//开始解析每个输出blobfloat *data = (float*)outs[i].data;for (int j = 0; j < outs[i].rows; j++,data+=outs[i].cols) {			//加入data+=outs[i].cols是为了跳到下一行去,data相当于指针,指针到下一行使用此种方式Mat scores = outs[i].row(j).colRange(5, outs[i].cols);Point classIdPoint;double confidence;minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);//[C, center_x, center_y, width, height]if (confidence > 0.5) {int centerx = (int)(data[0] * src.cols);int centery = (int)(data[1] * src.rows);int width = (int)(data[2] * src.cols);int height = (int)(data[3] * src.rows);int left = centerx - width / 2;int top = centery - height / 2;classIds.push_back(classIdPoint.x);boxes.push_back(Rect(left, top, width, height));rectangle(src, Rect(left, top, width, height), Scalar(0, 0, 255), 2, 8);}}}imshow("result", src);waitKey(0);return 0;
}

发现有多个框,这是没有做非最大抑制出现的。
OpenCVDNN模块已经提供了非最大抑制的API

Yolov3tiny 也可以尝试一下,速度较快,只有30M左右,精度较低
但对于实时性较高的场景,还是不错的

NMS可以去掉重复的检测框,但需要调试,根据结果选择调试

OpenCV_DNNIE_837">11-OpenCV DNN配置加速组件IE支持

代码演示部分,每层都有box框

对象检测,图像分类都用了,但他们的速度太慢

使用IE加速我们对模块的推理

英特尔发布的深度学习加速工具包,开源的
其中最重要的组件有IE

• OpenVINO中的IE加速组件介绍
• 设置IE为计算后台,加速执行
• 代码演示
注意在官方下载的是无加速的,需要自己编译,才能得到支持OpenCV版本的,此种方式较麻烦

我们无需编译,只需要安装openVINO就可以得到一个支持IE加速的版本

OpenVINO中的IE加速组件介绍
• 下载与安装IE支持的OpenCV版本
• 重新配置OpenCV
• 安装依赖(VS2015/VS2017+CMake3.14+Python3.6.5)
• https://software.intel.com/en-us/openvino-toolkit/choose-download

注意要有CMAKE3.14,的环境变量要配置,python3.6.5也要配置到环境变量中去
在这里插入图片描述

注意openvino只会从默认的安装目录去找,所以前面的不要自定义安装,默认安装即可

OpenCVvino路径是可以改的,可以改到
OpenCVvino中的OpenCV的lib,include等配置好

C:\Program Files (x86)\IntelSWTools\openvino_2020.4.287

只有通过OpenCVvino安装好后,才可以设置计算后台如下,否则会报错
net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
net.setPreferableTarget(DNN_TARGET_CPU);

可能对图片时,发现无法明显加速,前期是在加载模型,初始化权重方法,但一旦推断forward速度就会非常快
在这里插入图片描述

前面的caffe、TensorFlow、mxnet等平台的离线模型都可以通过OpenCV的DNN模块加载,加载开始计算时使用OpenCVDNN作为加载后台,现在有了opencvvino,就可以使用inference ENgine作为后台支持,而此后台又支持CPU\GPU\VPU加速,英伟达的GPU天生不支持,支持的是英特尔的图形卡的计算方式,如果想要支持需要自己想办法编译。
获得优化后可以得到5到10倍的加速,一秒钟可能5帧,现在就25帧了

代码实现
• 设置IE为计算后台
• 加速执行
• 支持网络与模型
• 关于转换IR与更多知识…

安装完成后需要测验一下

加速组件

https://cmake.org/files/v3.14/
https://www.python.org/downloads/release/python-365/

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

注意cmake和python3.6.5要默认路径安装,
Openvino可以更改路径安装
下面的路径就是推算引擎
C:\Program Files (x86)\IntelSWTools\openvino_2020.4.287\inference_engine

我们的是debug模式,要将下方的路径添加到环境变量
C:\Program Files (x86)\IntelSWTools\openvino_2020.4.287\inference_engine\bin\intel64\Debug

此处有OpenCV
C:\Program Files (x86)\IntelSWTools\openvino_2020.4.287\opencv
之前如何配置这里就怎么配置
OpenCV配置好后,此处就可以使用了

如何检测是否安装好了
C:\Program Files (x86)\IntelSWTools\openvino_2020.4.287\deployment_tools\demo
进入文件下,双击运行demo_security_barrier_camera.bat
等到最后弹出车牌检测图,说明所有安装都没有问题

在这里插入图片描述

使用openvino的OpenCV的属性配置,看能否
net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);运行。

opencv_calib3d440d.lib
opencv_core440d.lib
opencv_dnn440d.lib
opencv_features2d440d.lib
opencv_flann440d.lib
opencv_gapi440d.lib
opencv_highgui440d.lib
opencv_imgcodecs440d.lib
opencv_imgproc440d.lib
opencv_ml440d.lib
opencv_objdetect440d.lib
opencv_photo440d.lib
opencv_stitching440d.lib
opencv_video440d.lib
opencv_videoio440d.libinference_engine_c_apid.lib
inference_engine_ir_readerd.lib
inference_engine_legacyd.lib
inference_engine_lp_transformationsd.lib
inference_engine_onnx_readerd.lib
inference_engine_preprocd.lib
inference_engine_transformationsd.lib
inference_engined.lib

http://www.ppmy.cn/news/1519563.html

相关文章

NLP从零开始------15.文本中阶序列处理之语言模型(3)

4. 注意力机制 4.1 注意力机制 循环神经网络的一个主要局限是不能很好地建模长距离依赖&#xff0c;即使像长短期记忆这样的变体也只是改善而不是完全解决了长距离依赖的问题。其根本原因在于&#xff0c;如果序列中的第i个词需要对第j个词(假设j>i)产生影响&#xff0c;需…

024、架构_资源_主机

摘要 在主机管理界面,可查看 GoldenDB 使用的主机信息,可对主机执行新增、编辑、删除操作。 主机列表 选择菜单[资源管理→主机管理],进入主机列表界面。 新增主机(单个、批量) 新增主机流程: 添加

Gradio学习——图像流输出

对于在后端实时获取的视频帧&#xff0c;经过图像处理函数处理后&#xff0c;需要不停的返回给前端。由于不是固定的视频&#xff0c;无法用gr.Video()方法&#xff0c;那利用gradio应该怎么处理&#xff1f;方法如下&#xff1a; import gradio as gr import time import cv2…

CS224W—07 Machine Learning with Heterogeneous Graphs

CS224W—07 Machine Learning with Heterogeneous Graphs 本节中&#xff0c;我们将学习如何在异构图中进行图神经网络学习。 Heterogeneous Graphs 图中的节点类型/边类型不同&#xff0c;就会形成一个异构图&#xff08;Heterogeneous Graph&#xff09;&#xff0c;例如下…

情侣日记2.0.0_多种姿势卡_增进情侣感情必备工具

一款专门为情侣互动、增进感情而开发的一款软件&#xff1b;乐趣激情的游戏互动让你和ta的感情快速升温、拉近彼此的距离&#xff1b;恋爱话术技巧、享受甜蜜热恋&#xff1b;真心话大冒险、激情骰子、情侣飞行棋&#xff0c;享受生活小情趣&#xff01; 链接&#xff1a;http…

TensorFlow创建回归神经网络及Optimizer优化器

一.TensorFlow创建神经层 如图所示&#xff0c;通过该神经网络识别动物猫或狗&#xff0c;共包括输入层&#xff08;Input Layer&#xff09;、隐藏层3层&#xff08;Hidden Layer&#xff09;和输出层&#xff08;Output Layer&#xff09;。其中每个隐藏层神经元都有一个激励…

开学季儿童护眼台灯怎么选择?盘点央视公布十大护眼灯!

随着年级的升高和学习内容的增加&#xff0c;学生的休闲娱乐时间逐渐减少&#xff0c;相反&#xff0c;他们在书桌前度过的时间却越来越多。近年来&#xff0c;由于电子产品的广泛使用&#xff0c;我国青少年的用眼负担显著增加。据权威机构预测&#xff0c;到2050年&#xff0…

windows下安装docker操作步骤

因为最近dockerb被封&#xff0c;下载资源太不方便了&#xff0c;所以还是自己本地安装上docker吧 下载的地址一定不要找错&#xff0c;是这里 https://docs.docker.com/desktop/install/windows-install/ 电脑--“控制面板”--“程序与功能”--开启windows功能 “Hyper-V”…

实战docker第一天——windows安装docker,测试,并解决被墙办法

Docker 是一个开源的容器化平台&#xff0c;它允许开发者将应用程序及其所有依赖项打包在一个名为“容器”的单独环境中&#xff0c;从而确保应用程序在任何环境下都能一致地运行。以下是 Docker 的一些核心概念及其意义&#xff1a; 容器化&#xff1a;Docker 通过将应用程序及…

vrrp协议,主备路由器的选举

当VRRP备份组中的所有备份路由器&#xff08;BACKUP&#xff09;具有相同的优先级时&#xff0c;选举新的主路由器&#xff08;MASTER&#xff09;的过程将基于以下规则&#xff1a; IP地址优先&#xff1a;如果备份路由器的优先级相同&#xff0c;那么具有最高IP地址的路由器…

鱼哥好书分享活动第30期:一本书看完教你学习如何做B端竞品分析?《有效竞品分享》

鱼哥好书分享活动第30期&#xff1a;一本书看完教你学习如何做B端竞品分析&#xff1f;《有效竞品分享》 01 明确目标&#xff1a;案例分享&#xff1a;案例背景&#xff1a; 02 选择竞品&#xff1a;2.1 竞品的分类2.2 如何找到B端的竞品&#xff1f;1.找售前/销售沟通。2.各个…

C#护照查验接口集成示例、护照文字识别、外国人身份认证

护照查验是对护照有效性、真实性和符合相关出入境要求的确认过程。护照作为跨国旅行的重要身份证明文件&#xff0c;其查验是国际旅行中的一个必要程序。护照查验接口&#xff0c;支持查验出入境管理局签发护照的真伪&#xff0c;接口集成&#xff0c;简单高效便捷。 C#护照查验…

闲置物品|基于SprinBoot+vue的校园闲置物品交易平台(源码+数据库+文档)

校园闲置物品交易平台 目录 基于SprinBootvue的校园闲置物品交易平台 一、前言 二、系统设计 三、系统功能设计 5.1系统功能实现 5.2管理员模块实现 5.3用户模块实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xf…

Vue59 github案例 vue-resource版本

代码 List.vue <template><div class"row"><!-- 展示用户列表 --><div v-show"info.users.length" class"card" v-for"user in info.users" :key"user.login"><a :href"user.html_url&qu…

uniapp 生成H5 返回上一页 事件不执行

uniapp 生成H5 返回上一页事件不执行 背景&#xff1a;想根据返回的页面判断是否再返回一页 解决办法&#xff1a;uniapp&#xff0c;H5是先执行方法再返回&#xff0c;所以给事件增加延迟调用&#xff0c;如下代码 // 监听返回 onBackPress(e) {let pages getCurrentPages(…

数据结构(6.4_3)最短路径问题_Dijkstra算法

BFS的局限性 Dijkstra算法 1、 2、 3、 4、 如何使用数组信息 Dijkstra算法的时间复杂度 对比&#xff1a;Prim算法的实现思想 用于负权值带权图

docker实战基础三(Docker基础命令)

Docker 实战案例:构建镜像、查看容器运行信息、查看镜像构建信息 在这个实战案例中,我们将详细介绍如何构建Docker镜像、查看容器运行信息以及查看镜像构建信息。这些知识点非常实用,可以帮助你在实际工作中更好地利用Docker进行开发和运维。 一、构建Docker镜像 1. 创建…

【C++】C++STL 揭秘:Strng背后的底层逻辑

C语法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;命名空间缺省参数与函数重载C相关特性类和对象-上篇 在上篇介绍string类的使用与理解&#xff0c;本篇将为大家来带关于string的底层实现逻辑&#xff0c;当然这不是一定库里面的实现逻辑。我们设计一个string…

Android13 动态控制状态栏和导航栏

前言 在Android系统中,状态栏(StatusBar)、导航栏(NavigationBar)以及下拉菜单(通常称为Notification Shade或Quick Settings Panel)构成了用户界面不可或缺的三个元素,它们共同为用户提供了丰富的信息显示与便捷的交互体验。具体而言,状态栏实时展示着时间、电池电量…

DMDSC集群安装

1. 环境描述 机器情况&#xff1a; 存储情况&#xff1a; 2. 部署前准备 2.1. 目录规划和创建 创建和规划目录在2个节点都需要执行。 DSC环境搭建的目录&#xff1a;/dmdba/dmdbms DM执行码和工具存放于目录&#xff1a;/dmdba/dmdbms/bin 配置文件存放于目录&#xff1a…