在vs中用opencv3.3DNN模块调用训练好的caffe模型做分类

如何用caffe训练分类器参考这篇博客https://blog.csdn.net/sinat_41852207/article/details/88194744

 需要: caffe训练好的模型和对应的测试配置文件deploy.prototxt,

一个txt文件,里面有图片名

一个label.txt文件,里面写分类名,我是二分类,所以就两个

最后把分类好的图片放到不同的文件夹下,便于检查 

//从文件夹批量读取图片,用caffemodel测试分类效果
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>

using namespace cv;
using namespace cv::dnn;
using namespace std;
String modelTxt = "D:/software_engineer/caffe-master/examples/testImg/deploy.prototxt";//caffe的测试网络结构模型
String modelBin = "D:/software_engineer/caffe-master/examples/testImg/cifar10_quick_iter_10000.caffemodel";//caffe训练好的文件
String labelFile = "D:/software_engineer/caffe-master/examples/testImg/labels.txt";//训练的时候用0和1表示类别,利用这个文件把0和1对应到OK和NG
string ImgFile = "D:/images/total/imgName.txt";////从该txt文件读取图片名,txt里面是图片名 如10.jpg
string saveRoadOK = "D:/images/OK/" ;//最后输出保存OK图片的路径
string saveRoadNG = "D:/images/NG/" ;//最后输出保存NG图片的路径,我是二分类,所以输出为两个文件

vector<String> readClasslabels();

int main(int argc, char** argv) {
	ifstream fin(ImgFile, ios::in);
	//char line[1024] = { 0 };
	string line;
	while (getline(fin, line))
	{
		cout << "Image Name: " << line << endl;
		string imgRoad = "D:/images/total/" + line;//图片的绝对路径名
		Mat testImage = imread(imgRoad);
		if (testImage.empty()) 
		{
			printf("could not load image...\n");
			waitKey(0);
			return -1;
		}
		// create lenet with caffemodel text and bin
		Net net = readNetFromCaffe(modelTxt, modelBin);
		if (net.empty())
		{
			cerr << "Can't load network by using the following files: " << endl;
			cerr << "prototxt:   " << modelTxt << endl;
			cerr << "caffemodel: " << modelBin << endl;
			return -1;
		}
		// 读取分类数据
		vector<String> labels = readClasslabels();
		Mat inputBlob = blobFromImage(testImage, 1.0, Size(32, 32), Scalar(0, 0, 0));//size为32*32由训练模型确定,后一个参数为减均值操作,这里我没有减均值
		Mat prob;
		net.setInput(inputBlob, "data");//“data”是deploy.prototxt里第一层名字
		// 分类预测
		prob = net.forward("prob");//“prob”是deploy.prototxt里最后一层名字
		// 读取分类索引,最大与最小值
		Mat probMat = prob.reshape(1, 1); 
		Point classNumber;
		double classProb;
		minMaxLoc(probMat, NULL, &classProb, NULL, &classNumber); // 可能性最大的一个
		int classIdx = classNumber.x; // 分类索引号
		//printf("\n current image classification : %s, possible : %.2f \n", labels.at(classIdx).c_str(), classProb);
		string className = labels.at(classIdx);//类名(ok ng)               .c_str()
		cout << "current image classification :"<<className << endl;
		printf("---------------------------------------------------------\n");
		if (className=="OK")
		{
			imwrite(saveRoadOK + line, testImage);
		}
		else
		{
			imwrite(saveRoadNG + line, testImage);
		}
		putText(testImage, labels.at(classIdx), Point(20, 20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 255), 2, 8);//在图片上写字
		imshow("Image Category", testImage);
	}
	fin.clear();
	fin.close();
	waitKey(0);
	return 0;
}
// 读取图像的1000个分类标记文本数据 
vector<String> readClasslabels() {
	vector<String> classNames;
	ifstream fp(labelFile);
	if (!fp.is_open())
	{
		cerr << "File with classes labels not found: " << labelFile << endl;
		exit(-1);
	}
	string name;
	while (!fp.eof())
	{
		getline(fp, name);
		if (name.length())
			classNames.push_back(name.substr(name.find(' ') + 1));
	}
	fp.close();
	return classNames;
}




最后运行结果: 

发布了59 篇原创文章 · 获赞 46 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/sinat_41852207/article/details/88197593