opencv_DNN模块加载caffe模型

这篇博客介绍了如何在Windows和Linux aarch64平台上利用OpenCV的DNN模块进行GoogLeNet模型的图像分类。首先,确保OpenCV版本在3.3以上,并配置好VS环境。代码中定义了加载模型、预处理图像、读取标签文件、进行模型推理和解析结果的步骤。在Windows环境下,通过VS运行代码并显示分类结果;而在Linux aarch64上,虽然缺少GUI依赖,但可以通过修改CMakeLists.txt文件来编译和运行代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

caffe_GoogLeNet_opencv_DNN.zip-嵌入式文档类资源-CSDN下载

Windows

DNN模块需要opencv版本是3.3以上。配置VS环境加入opencv路径。

代码逻辑:

  1. 预设文件加载路径;
  2. 加载图片;
  3. 读取标签文件类别名称,存储到vector变量中。
  4. API调用caffe模型;
  5. 输入图片数据需要格式转换;
  6. 前向推理模型,得到结果;
  7. 对结果数据进行reshape,找到结果中比例最大值位置信息;
  8. 打印对应位置类别名称;

main.cpp

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <fstream>

// 模型描述文件prototxt
std::string model_txt_file = "G:/3_OpenCV/code/DNNCode/testDNN/testDNN/testDNN/bvlc_googlenet.prototxt";
// 二进制caffe模型文件
std::string model_bin_file = "G:/3_OpenCV/code/DNNCode/testDNN/testDNN/testDNN/bvlc_googlenet.caffemodel";
// 模型label标签文件
std::string labels_txt_file = "G:/3_OpenCV/code/DNNCode/testDNN/testDNN/testDNN/synset_words.txt";

std::vector<std::string> readLabels();	// 读取标签文件

/*
 * 主函数
 */
int main(int argc, int* argv[]) {
	cv::Mat src = cv::imread("a.jpg");	// 读取图片
	if (src.empty()) {					// 数据非空
		printf("Could not load image...\n");
		return -1;
	}
	cv::namedWindow("input", CV_WINDOW_AUTOSIZE);
	cv::imshow("input", src);			// 显示原图像

	std::vector<std::string> labels = readLabels();		// 读取存储标签文件
	// 加载caffe模型文件,输入模型描述文件,二进制模型caffemodel
	cv::dnn::Net net = cv::dnn::readNetFromCaffe(model_txt_file, model_bin_file);
	if (net.empty()) {					// 模型文件非空
		printf("read caffe model data failure...\n");
		return -1;
	}
	// 转换输入图片文件格式,缩放比例,尺寸,归一化
	cv::Mat intputBlob = cv::dnn::blobFromImage(src, 1.0, cv::Size(224, 224), cv::Scalar(104, 117, 123));
	cv::Mat prob;		// 
	for (int i = 0; i < 10; i++) {			// 为啥循环做推理
		net.setInput(intputBlob, "data");	// 设置输入数据,名称与模型描述文件输入一致
		prob = net.forward("prob");			// 设置输出名称,与模型描述文件输入一致
	}
	cv::Mat probMat = prob.reshape(1, 1);	// reshape成1行1000列
	cv::Point classNumber;					// 存储类别位置的坐标
	double classProb;						// 存储类别的名称
	// 寻找类别向量中,最大值,最小值的位置和数值
	cv::minMaxLoc(probMat, NULL, &classProb, NULL, &classNumber);
	int classidx = classNumber.x;	// 保存最大值的X坐标
	printf("\n current image classification : %s, possible : %.2f", labels.at(classidx).c_str(), classProb);
	putText(src, labels.at(classidx), cv::Point(20, 20), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(0, 0, 255), 2, 8);

	cv::imshow("Image Classification", src);
	cv::waitKey(0);
	return 0;
}



/* 
 * 读取标签文件 
 */
std::vector<std::string> readLabels() {
	std::vector<std::string> classNames;	// 存储所有类别名称
	std::ifstream fp(labels_txt_file);		// 打开标签文件
	if (!fp.is_open()) {					// 如果没有打开
		printf("Could not open the file");
		exit(-1);
	}
	std::string name;			// 存储一行类别名称的内容
	while (!fp.eof()) {			// 没有的读取到最后一行就继续读取
		std::getline(fp, name);	// 读取一行,存储到变量
		if (name.length()) {	// 如果有数据
			// 找到一行中空格,到后面的1个字符,存储到向量的后面
			classNames.push_back(name.substr(name.find(' ') + 1));
		}
	}
	fp.close();
	return classNames;
}






 

Linux aarch64

需要编译安装aarch64架构的opencv,RK3399编译安装opencv版本为4.5。但是缺少GUI依赖包,安装之后没有解决。

       要运行代码,需要相应修改CmakeList.txt文件内容即可。

CMakeList.txt

cmake_minimum_required(VERSION 3.10)
project( DisplayImage )

find_package( OpenCV REQUIRED )

add_executable( DisplayImage src/main.cpp )
target_link_libraries( DisplayImage ${OpenCV_LIBS})

main.cpp

#include <opencv2/opencv.hpp>
//#include <opencv2/highgui/highgui_c.h>
#include <fstream>

// 模型描述文件prototxt
std::string model_txt_file = "/home/orangepi/Desktop/caffeDNNtest/src/bvlc_googlenet.prototxt";
// 二进制caffe模型文件
std::string model_bin_file = "/home/orangepi/Desktop/caffeDNNtest/src/bvlc_googlenet.caffemodel";
// 模型label标签文件
std::string labels_txt_file = "/home/orangepi/Desktop/caffeDNNtest/src/synset_words.txt";

std::vector<std::string> readLabels();	// 读取标签文件

/*
 * 主函数
 */
int main(int argc, char** argv) {
	cv::Mat src = cv::imread("/home/orangepi/Desktop/caffeDNNtest/src/a.jpg");	// 读取图片
	if (src.empty()) {					// 数据非空
		printf("Could not load image...\n");
		return -1;
	}
	//cv::namedWindow("input", CV_WINDOW_AUTOSIZE);
	//cv::imshow("input", src);			// 显示原图像

	std::vector<std::string> labels = readLabels();		// 读取存储标签文件
	// 加载caffe模型文件,输入模型描述文件,二进制模型caffemodel
	cv::dnn::Net net = cv::dnn::readNetFromCaffe(model_txt_file, model_bin_file);
	if (net.empty()) {					// 模型文件非空
		printf("read caffe model data failure...\n");
		return -1;
	}
	// 转换输入图片文件格式,缩放比例,尺寸,归一化
	cv::Mat intputBlob = cv::dnn::blobFromImage(src, 1.0, cv::Size(224, 224), cv::Scalar(104, 117, 123));
	cv::Mat prob;		// 
	for (int i = 0; i < 10; i++) {			// 为啥循环做推理
		net.setInput(intputBlob, "data");	// 设置输入数据,名称与模型描述文件输入一致
		prob = net.forward("prob");			// 设置输出名称,与模型描述文件输入一致
	}
	cv::Mat probMat = prob.reshape(1, 1);	// reshape成1行1000列
	cv::Point classNumber;					// 存储类别位置的坐标
	double classProb;						// 存储类别的名称
	// 寻找类别向量中,最大值,最小值的位置和数值
	cv::minMaxLoc(probMat, NULL, &classProb, NULL, &classNumber);
	int classidx = classNumber.x;	// 保存最大值的X坐标
	printf("\ncurrent image classification : %s, possible : %.2f\n", labels.at(classidx).c_str(), classProb);
	//putText(src, labels.at(classidx), cv::Point(20, 20), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(0, 0, 255), 2, 8);

	//cv::imshow("Image Classification", src);
	//cv::waitKey(0);
	return 0;
}



/* 
 * 读取标签文件 
 */
std::vector<std::string> readLabels() {
	std::vector<std::string> classNames;	// 存储所有类别名称
	std::ifstream fp(labels_txt_file);		// 打开标签文件
	if (!fp.is_open()) {					// 如果没有打开
		printf("Could not open the file");
		exit(-1);
	}
	std::string name;			// 存储一行类别名称的内容
	while (!fp.eof()) {			// 没有的读取到最后一行就继续读取
		std::getline(fp, name);	// 读取一行,存储到变量
		if (name.length()) {	// 如果有数据
			// 找到一行中空格,到后面的1个字符,存储到向量的后面
			classNames.push_back(name.substr(name.find(' ') + 1));
		}
	}
	fp.close();
	return classNames;
}






 

 

 

 

 

 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值