基于C++的OpenCV4高级知识–深度神经网络(DNN)基础

不管现实多么惨不忍睹,都要持之以恒地相信,这只是黎明前短暂的黑暗而已。不要惶恐眼前的难关迈不过去,不要担心此刻的付出没有回报,别再花时间等待天降好运。真诚做人,努力做事!你想要的,岁月都会给你。基于C++的OpenCV4高级知识–深度神经网络(DNN)基础,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

1,模块介绍
OpenCV中的深度学习模块(DNN)只提供了推理功能,不涉及模型的训练,支持多种深度学习框架,比如TensorFlow,Caffe,Torch和Darknet。
轻量型。DNN模块只实现了推理功能,代码量及编译运行开销远小于其他深度学习模型框架。
使用方便。DNN模块提供了内建的CPU和GPU加速,无需依赖第三方库,若项目中之前使用了OpenCV,那么通过DNN模块可以很方便的为原项目添加深度学习的能力。
通用性。DNN模块支持多种网络模型格式,用户无需额外的进行网络模型的转换就可以直接使用,支持的网络结构涵盖了常用的目标分类,目标检测和图像分割的类别
在这里插入图片描述
2,OpenCV DNN 中支持的模型
在这里插入图片描述
3,OpenCV DNN 中支持的功能
图像分类、对象检测、图像分割、场景文字检测、人脸检测与识别

4,接口用法
4.1加载一个DNN网络 ,API:readNet、readNetFromCaffe、readNetFromTensorflow等等从不同的模块加载网络

//以caffemodel为例
  CV_EXPORTS_W Net readNetFromCaffe(const String &prototxt, const String &caffeModel = String());

加载网络

	#include<opencv2/opencv.hpp>
	#include<opencv2/dnn.hpp>//包含DNN模块头文件
	#include<iostream>

	using namespace std;
	using namespace cv;
	using namespace cv::dnn;
	
	//以bvlc_googlenet.caffemodel为例
	
	string bin_model = "F:/code/opencv_tutorial/data/models/googlenet/bvlc_googlenet.caffemodel";//模型的权重文件
	string protxt = "F:/code/opencv_tutorial/data/models/googlenet/bvlc_googlenet.prototxt";//模型的描述文件
	
	//Load DNN model
	Net net = readNetFromCaffe(protxt, bin_model);

4.2获取各个层的信息

	//获取各层信息
	vector<string> layer_names = net.getLayerNames();
	cout << "layer id :" <<" "<< "layer type:" << "                       " << "layer name:" << endl;
	for (int i = 0; i < layer_names.size(); i++) {
		int id = net.getLayerId(layer_names[i]);
		auto layer = net.getLayer(id);
		cout << id << " " << layer->type.c_str() << "                       " << layer->name.c_str() << endl;
	}

4.3设置计算后台与支持设备

	//设置计算后台
	net.setPreferableBackend(DNN_BACKEND_OPENCV);
	//设置支持设备
	net.setPreferableTarget(DNN_TARGET_CPU);

4.4设置输入
dnn.blobFromImage
作用:根据输入图像,创建维度N(图片的个数),通道数C,高H和宽W次序的blobs。

blobFromImage(image, 
              scalefactor=None, 
              size=None, 
              mean=None, 
              swapRB=None, 
              crop=None, 
              ddepth=None):

参数:
image:cv2.imread 读取的图片数据
scalefactor: 缩放像素值,如 [0, 255] – [0, 1]
size: 输出blob(图像)的尺寸,如 (netInWidth, netInHeight)
mean: 从各通道减均值. 如果输入 image 为 BGR 次序,且swapRB=True,则通道次序为 (mean-R, mean-G, mean-B).
swapRB: 交换 3 通道图片的第一个和最后一个通道,如 BGR – RGB
crop: 图像尺寸 resize 后是否裁剪. 如果crop=True,则,输入图片的尺寸调整resize后,一个边对应与 size 的一个维度,而另一个边的值大于等于 size 的另一个维度;然后从 resize 后的图片中心进行 crop. 如果crop=False,则无需 crop,只需保持图片的长宽比
ddepth: 输出 blob 的 Depth. 可选: CV_32F 或 CV_8U

示例:

img_cv2 = cv2.imread("test.jpeg")
 
inWidth = 256
inHeight = 256
cv::Mat blob = cv2.dnn.blobFromImage(img_cv2,
                                scalefactor=1.0 / 255,
                                size=(inWidth, inHeight),
                                mean=(0, 0, 0),
                                swapRB=False,
                                crop=False)

4.5设置网络模型输入:

net.setInput(blob);
output = net.forward();

4.6执行网络推理并得到输出结果:

out=net.forward()

5,完整代码示例

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/dnn.hpp>
#include <iostream>
#include <fstream>
using namespace cv;
using namespace std;
using namespace cv::dnn;
String model_bin_file = "model/bvlc_googlenet.caffemodel";
String model_txt_file = "model/bvlc_googlenet.prototxt";
String labels_txt_file = "model/synset_words.txt";
vector<String> readLabels();
int main(int argc, char** argv)
{
	Mat src = imread("pictures/girl.jpg");
	if (src.empty())
	{
		cout << "could not open image……" << endl;
		return -1;
	}
	namedWindow("src", WINDOW_FREERATIO);
	imshow("src", src);
	// 读取labels
	vector<String> labels = readLabels();
	// 读取网络 包括模型描述文件和和模型文件
	Net net = readNetFromCaffe(model_txt_file, model_bin_file);
	if (net.empty())
	{
		cout << "net could not load……" << endl;
		return -1;
	}
	Mat inputBlob = blobFromImage(src, 1.0, Size(224, 224), Scalar(104, 117, 123));
	Mat prob;
	for (size_t i = 0; i < 10; i++)
	{
		net.setInput(inputBlob, "data");
		prob = net.forward("prob");	// 输出为1×1000 1000类的概率
	}
	Mat proMat = prob.reshape(1, 1);	// 单通道 一行
	Point classNumber;
	double classProb;
	minMaxLoc(proMat, NULL, &classProb, NULL, &classNumber);
	int classidx = classNumber.x;
	cout << "current image classification:" << labels.at(classidx).c_str() 
		 << "possible:" << classProb <<  endl;
	putText(src, labels.at(classidx), Point(20, 20), FONT_HERSHEY_PLAIN, 1.5, Scalar(0, 0, 255), 1, 8);
	imshow("image", src);
	waitKey(0);
	return 0;
}
vector<String> readLabels()
{
	vector<String> classNames;
	ifstream fin(labels_txt_file.c_str());
	if (!fin.is_open())
	{
		cout << "could not open the file……" << endl;
		exit(-1);
	}
	string name;
	while (!fin.eof())
	{
		getline(fin, name);
		if (name.length())
		{
			classNames.push_back(name.substr(name.find(" " + 1)));// 按空格的位置往后移一位进行分割

		}
	}
	fin.close();
	return classNames;
}

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/182004.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!