图像分类项目(三):opencv读取自定义的pb模型,自定义softmax,argmax函数输出图像分类结果

自定义数据集、模型,用QT、c++调用tensorflow编译好的pb模型的图像分类项目
第一步:制作自己的TFRecord数据集,读取并显示(详细图解)
第二步:读取自定义的TFRecord数据集,训练卷积网络并保存pb模型
第三步:本文
流程图:
在这里插入图片描述
前面已经保存了训练好的pb模型,下面就来验证模型是否可以使用以及效果。

代码如下

#include<opencv2/opencv.hpp>
#include<opencv2/dnn.hpp>

#include<iostream>
#include<string.h>

using namespace cv;
using namespace std;
using namespace dnn;

//计算一列数中最大值的索引
int argmax(cv::Mat mat, int n) {
	int index = 0;
	float max = mat.at<float>(0, 0);
	float cur = mat.at<float>(0, 0);
	for (int i = 0; i < n; i++) {
		cur = mat.at<float>(0, i);
		if (cur > max) {
			max = cur;
			index = i;
		}
	}
	return index;
}

// C++/Opencv实现softmax函数。
int softmax(const Mat& src, Mat& dst, int length) {
	float max = 0.0;
	float sum = 0.0;
	for (int i = 0; i < length; i++) {
		if (max < src.at<float>(0, i))
			max = src.at<float>(0, i);
	}
	for (int i = 0; i < length; i++) {
		dst.at<float>(0, i) = exp(src.at<float>(0, i) - max);
		sum += dst.at<float>(0, i);
	}

	for (int i = 0; i < length; i++) {
		dst.at<float>(0, i) /= sum;
	}
	return 0;
}

int main() {

	int width = 100;
	int height = 100;

	cv::Mat src = cv::imread("flower_photos/daisy/517054463_036db655a1_m.jpg");
	resize(src, src, cv::Size(width, height));
	cv::namedWindow("input", CV_WINDOW_AUTOSIZE);
	cv::imshow("input", src);

	try
	{
		cv::String weights = "flower_cnn.pb";

		dnn::Net net = cv::dnn::readNetFromTensorflow(weights);

		//将图像转为神经网络输入的对象,由描述文件可知,图像尺寸统一为100*100
		cv::Mat inputBlob = cv::dnn::blobFromImage(src, 0.00390625f, Size(width, height), Scalar(), true, false);
		net.setInput(inputBlob, "input"); //设置网络输入,“数据”是输入层的名称
		// 执行图像分类
		Mat output = net.forward("output");

		cout << output << endl;

		Mat dst = output.clone();//深复制,用copyTo或者clone
		softmax(output, dst, output.cols);
		cout << dst << endl;

		cout << argmax(dst, output.cols) << endl;
	}
	catch (const std::exception&)
	{
		std::system("pause");
	}

	cv::waitKey(0);
	return 0;
}

注意事项:
1.可以看到output的结果为一维数组,因为在前面模型保存output节点时,output是卷积层的输出结果乘以1。输出节点不能是softmax后的节点,cv::dnn::readNetFromTensorflow函数无法识别softmax层。只能自己得到一维数组然后用C++处理。
2.关于blobFromImage函数有两个需要注意的地方。我们看前面的Tensorflow模型会发现,模型的x节点是读取tfrecords模型后的数据经过归一化的,所以这里不能直接输入原数据,也要归一化,即1/255=0.00390625f。可以看到第5个参数bool swapRB为true,这是因为opencv读取图像时默认是BGR色彩空间,而通常的色彩空间是RGB,所以输入的数据色彩空间也要转换下。要么这里参数选true,要么用cvtcolor(src, src, BRG2RGB)转换后,参数选false。

结果测试

5种类别各输入一张图片,测试结果。
输入一张雏菊图片,结果如下0,正确
在这里插入图片描述
输入一张蒲公英图片,结果如下1,正确
在这里插入图片描述
输入一张玫瑰图片,结果如下2,正确
在这里插入图片描述
输入一张向日葵图片,结果如下3,正确
在这里插入图片描述
输入一张郁金香图片,结果如下4,正确
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值