caffe-3.1--(本机PC上一个完整独立的测试程序)--MFC前台+调用Caffe后台

作者:daska110

原因:因为界面和caffe不是一个程序,需要整合。

目标:在MFC前台显示一张图片,当点击“开始测试”时,得到识别率并显示在界面上

需要传入图片路径,将图片路径写入*.bat里,运行*.bat,找到输出的识别率,显示在MFC界面上。


controledit初始化

// TODO:  在此添加额外的初始化代码
CEdit* pBox1;
pBox1 = (CEdit*)GetDlgItem(IDC_EDIT1);
CString CStrRecordData = CString("F:\\caffe-master170309\\examples\\cifar10\\194357.png");
pBox1->SetWindowText(CStrRecordData);


按钮的事件响应函数,基本功能已实现,但没有显示图片

void CMFCCaffe1Dlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	// 1. 输入图片路径,送入str变量 // http://www.cnblogs.com/visionfeng/p/5611214.html
	CEdit* pBox1;
	pBox1 = (CEdit*)GetDlgItem(IDC_EDIT1);
	CString strpicPath;
	pBox1->GetWindowText(strpicPath);
	pBox1->SetWindowText(strpicPath);
	
	// fstream清空文件
	char* strRecordTxtPath = "F:\\caffe-master170309\\examples\\cifar10\\cmdOutputRecord.txt";
	std::fstream f1(strRecordTxtPath, std::fstream::out | std::ios_base::trunc);
	f1.close();


	// 2. 将str写入*.bat文件
	std::fstream f;
	std::string strBatPath = "F:\\caffe-master170309\\Build\\x64\\Debug\\calssfication.bat";
	f.open(strBatPath, std::ios::out);
	if (f)
	{
		std::string str1 = "F:\\caffe-master170309\\Build\\x64\\Debug\\classification.exe";
		std::string str2 = "F:\\caffe-master170309\\examples\\cifar10\\cifar10_quick.prototxt";
		std::string str3 = "F:\\caffe-master170309\\examples\\cifar10\\cifar10_quick_iter_400.caffemodel.h5";
		std::string str4 = "F:\\caffe-master170309\\examples\\cifar10\\mean.binaryproto";
		std::string str5 = "F:\\caffe-master170309\\examples\\cifar10\\synset_words.txt";
		std::string str6 = strpicPath + " >" + strRecordTxtPath;				// 不pause的话,cmd一闪而过即可
	//	std::string str6 = strpicPath + " >" + strRecordTxtPath + "\n\npause";  // 在EDIT1输入"F:\caffe-master170309\examples\cifar10\194357.png";
		std::string strall = str1 + " " + str2 + " " + str3 + " " + str4 + " " + str5 + " " + str6;
 
		f << strall;
// 		f << "F:\\caffe-master170309\\Build\\x64\\Debug\\classification.exe F:\\caffe-master170309\\examples\\cifar10\\cifar10_quick.prototxt F:\\caffe-master170309\\examples\\cifar10\\cifar10_quick_iter_400.caffemodel.h5 F:\\caffe-master170309\\examples\\cifar10\\mean.binaryproto F:\\caffe-master170309\\examples\\cifar10\\synset_words.txt F:\\caffe-master170309\\examples\\cifar10\\194357.png \n\npause";
		f.close();
	}


	// 3. MFC中调用"F:\\caffe-master170309\\Build\\x64\\Debug\\calssfication.bat"程序
  	system(strBatPath.c_str());        // http://blog.csdn.net/u011867581/article/details/44161787

	// 4. 找到Caffe测试(识别)的结果(已保存到F:\\caffe-master170309\\examples\\cifar10\\cmdOutputRecord.txt里),并输出到Edit2上
	std::fstream fRecord;
	fRecord.open(strRecordTxtPath, std::ios::in);
	if (fRecord)
	{
//		std::istreambuf_iterator<char> beg(fRecord), end; // https://wenku.baidu.com/view/9f387877172ded630a1cb699.html
//		std::string recordData(beg, end);

		std::string recordData;
		std::string line;
		while (getline(fRecord, line))  // http://blog.csdn.net/guowenyan001/article/details/11231927
		{
			std::string s1 = line;
			std::string s2 = std::string("\r\n\n");
			std::string s3 = s1 + s2;
			char *cs3 = const_cast<char*>(s3.c_str());

			recordData += std::string(cs3);
		}

		CEdit* pBox3;
		pBox3 = (CEdit*)GetDlgItem(IDC_EDIT3);
		CString CStrRecordData = CString(recordData.c_str());
		pBox3->SetWindowText(CStrRecordData);

		fRecord.close();
	}


最终的效果:(根据输入的png路径,打开png并转换存储为bmp图片,通过picControl空间动态加载bmp图片),效果如下:

工程下载:链接:http://pan.baidu.com/s/1miI4J5u 密码:mh96


void CMFCCaffe1Dlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	// 0. 输入图片路径,送入str变量 // http://www.cnblogs.com/visionfeng/p/5611214.html
	CEdit* pBox1;
	pBox1 = (CEdit*)GetDlgItem(IDC_EDIT1);
	CString strPicPath;
	pBox1->GetWindowText(strPicPath);
	pBox1->SetWindowText(strPicPath);
	
	// 1. 动态加载bmp图片
	CImage img;
//	img.Load(_T("F:\\caffe-master170309\\examples\\cifar10\\194357.png")); // http://blog.csdn.net/akof1314/article/details/5167279
//	img.Save(_T("F:\\caffe-master170309\\examples\\cifar10\\194357.bmp")); // http://bbs.csdn.net/topics/380029681 最底下
	img.Load(strPicPath);												   // http://blog.csdn.net/akof1314/article/details/5167279
	strPicPath.Replace(CString("png"), CString("bmp"));					   // "F:\\caffe-master170309\\examples\\cifar10\\194357.png"变为"F:\\caffe-master170309\\examples\\cifar10\\194357.bmp"
	img.Save(strPicPath);											       // http://bbs.csdn.net/topics/380029681 最底下
	
	/*
	CBitmap bitmap;								// CBitmap对象,用于加载位图   // http://www.jizhuomi.com/software/193.html
	HBITMAP hBmp;								// 保存CBitmap加载的位图的句柄
	bitmap.LoadBitmap(IDB_BITMAP1);				// 将位图IDB_BITMAP1加载到bitmap
	hBmp = (HBITMAP)bitmap.GetSafeHandle();		// 获取bitmap加载位图的句柄
	m_jzmPicture.SetBitmap(hBmp);				// 设置图片控件m_jzmPicture的位图图片为IDB_BITMAP1
	*/

	CString  m_strfile;
	CRect r;
	GetClientRect(&r);
	// 格式char*转为LPCWSTR  // http://blog.csdn.net/zhouxuguang236/article/details/8761497
	char* szStr = "F:\\caffe-master170309\\examples\\cifar10\\194357.bmp";
	CString str = CString(szStr);
	USES_CONVERSION;
	LPCWSTR wszClassName = A2CW(W2A(str));
	str.ReleaseBuffer();

	HBITMAP  hbitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
		wszClassName,
		IMAGE_BITMAP,
		r.Width() / 2,
		r.Height() / 2,
		LR_LOADFROMFILE);
	m_jzmPicture.SetBitmap(hbitmap);				// 设置图片控件m_jzmPicture的位图图片为IDB_BITMAP1  


	// 2. 将str写入*.bat文件
	
	// fstream清空文件
	char* strRecordTxtPath = "F:\\caffe-master170309\\examples\\cifar10\\cmdOutputRecord.txt";
	std::fstream f1(strRecordTxtPath, std::fstream::out | std::ios_base::trunc);
	f1.close();

	std::fstream f;
	std::string strBatPath = "F:\\caffe-master170309\\Build\\x64\\Debug\\calssfication.bat";
	f.open(strBatPath, std::ios::out);
	if (f)
	{
		std::string str1 = "F:\\caffe-master170309\\Build\\x64\\Debug\\classification.exe";
		std::string str2 = "F:\\caffe-master170309\\examples\\cifar10\\cifar10_quick.prototxt";
		std::string str3 = "F:\\caffe-master170309\\examples\\cifar10\\cifar10_quick_iter_400.caffemodel.h5";
		std::string str4 = "F:\\caffe-master170309\\examples\\cifar10\\mean.binaryproto";
		std::string str5 = "F:\\caffe-master170309\\examples\\cifar10\\synset_words.txt";
		std::string str6 = strPicPath + " >" + strRecordTxtPath;				// 不pause的话,cmd一闪而过即可
	//	std::string str6 = strPicPath + " >" + strRecordTxtPath + "\n\npause";  // 在EDIT1输入"F:\caffe-master170309\examples\cifar10\194357.png";
		std::string strall = str1 + " " + str2 + " " + str3 + " " + str4 + " " + str5 + " " + str6;
 
		f << strall;
// 		f << "F:\\caffe-master170309\\Build\\x64\\Debug\\classification.exe F:\\caffe-master170309\\examples\\cifar10\\cifar10_quick.prototxt F:\\caffe-master170309\\examples\\cifar10\\cifar10_quick_iter_400.caffemodel.h5 F:\\caffe-master170309\\examples\\cifar10\\mean.binaryproto F:\\caffe-master170309\\examples\\cifar10\\synset_words.txt F:\\caffe-master170309\\examples\\cifar10\\194357.png \n\npause";
		f.close();
	}


	// 3. MFC中调用"F:\\caffe-master170309\\Build\\x64\\Debug\\calssfication.bat"程序
  	system(strBatPath.c_str());        // http://blog.csdn.net/u011867581/article/details/44161787

	// 4. 找到Caffe测试(识别)的结果(已保存到F:\\caffe-master170309\\examples\\cifar10\\cmdOutputRecord.txt里),并输出到Edit2上
	std::fstream fRecord;
	fRecord.open(strRecordTxtPath, std::ios::in);
	if (fRecord)
	{
//		std::istreambuf_iterator<char> beg(fRecord), end; // https://wenku.baidu.com/view/9f387877172ded630a1cb699.html
//		std::string recordData(beg, end);

		std::string recordData;
		std::string line;
		while (getline(fRecord, line))  // http://blog.csdn.net/guowenyan001/article/details/11231927
		{
			std::string s1 = line;
			std::string s2 = std::string("\r\n\n");
			std::string s3 = s1 + s2;
			char *cs3 = const_cast<char*>(s3.c_str());

			recordData += std::string(cs3);
		}

		CEdit* pBox3;
		pBox3 = (CEdit*)GetDlgItem(IDC_EDIT3);
		CString CStrRecordData = CString(recordData.c_str());
		pBox3->SetWindowText(CStrRecordData);

		fRecord.close();
	}




参考:MFC中Edit Control值的获取与赋值  设置controledit初始化

vc调用*.bat文件12  VC中如何调用其他的可执行程序

cmd输出到txt

MFC通过PicControl控件加载bmp图像1  2


第二步:“MFC+Caffe的程序"改为批处理

效果如下:(控制台界面会一闪一闪,只有最后一张图的识别结果能显示在界面上)

主要是因为:速度慢,因为把jpg转为bmp才画出来的。




改进点:

1. 加时间戳

2. 存两个txt,一个是完整的classfication.bat运行的结果从cmd重定向到txt输出的结果,另一个是上述结果的解析(包含两列:一列是图片路径;另一列是该图片的识别结果)

代码如下:

if (strTmp == ".png")
				{
					// 1. 将str写入*.bat文件,并将*.bat文件运行结果从cmd从定向到txt输出
					std::fstream f_classficationbat;
					std::string strBatPath = "F:\\caffe-master170309\\Build\\x64\\Debug\\calssfication.bat";
					f_classficationbat.open(strBatPath, std::ios::out);
					if (f_classficationbat)
					{
						std::string str1 = "F:\\caffe-master170309\\Build\\x64\\Debug\\classification.exe";
						std::string str2 = "F:\\caffe-master170309\\examples\\cifar10\\cifar10_quick.prototxt";
						std::string str3 = "F:\\caffe-master170309\\examples\\cifar10\\cifar10_quick_iter_400.caffemodel.h5";
						std::string str4 = "F:\\caffe-master170309\\examples\\cifar10\\mean.binaryproto";
						std::string str5 = "F:\\caffe-master170309\\examples\\cifar10\\synset_words.txt";
						std::string str6 = pathStr_EachFileInFolders + " >>" + strRecognizeResultRecordFromCmdTxt;		// 不pause的话,cmd一闪而过即可, "<<"为将cmd追加输出至txt
						//	std::string str6 = pathStr_OnePic + " >" + f_RecognizeResultRecordFromCmdTxt + "\n\npause";  // 在EDIT1输入"F:\caffe-master170309\examples\cifar10\194357.png";
						std::string strall = str1 + " " + str2 + " " + str3 + " " + str4 + " " + str5 + " " + str6;

						f_classficationbat << strall << std::endl << std::endl;
						// f << "F:\\caffe-master170309\\Build\\x64\\Debug\\classification.exe F:\\caffe-master170309\\examples\\cifar10\\cifar10_quick.prototxt F:\\caffe-master170309\\examples\\cifar10\\cifar10_quick_iter_400.caffemodel.h5 F:\\caffe-master170309\\examples\\cifar10\\mean.binaryproto F:\\caffe-master170309\\examples\\cifar10\\synset_words.txt F:\\caffe-master170309\\examples\\cifar10\\194357.png \n\npause";
						f_classficationbat.close();
					}

					// 2. MFC中调用"F:\\caffe-master170309\\Build\\x64\\Debug\\calssfication.bat"程序
					system(strBatPath.c_str());        // http://blog.csdn.net/u011867581/article/details/44161787

					// 3. 将结果整理,解析到另一个txt(AnalysisOfRecognitionfromCmdTxt.txt)里,并显示在界面上	
					std::fstream f_AnalysisOfRecognitionFromCmdTxt;
					char* strAnalysisOfRecognitionFromCmdTxt = "F:\\caffe-master170309\\examples\\cifar10\\AnalysisOfRecognitionfromCmdTxt.txt";// 识别结果的解析txt
					f_AnalysisOfRecognitionFromCmdTxt.open(strAnalysisOfRecognitionFromCmdTxt, std::ios::out);
					if (f_AnalysisOfRecognitionFromCmdTxt)
					{
						std::fstream f_RecognizeResultRecordFromCmdTxt_2;
						char* strAnalysisOfRecognitionFromCmdTxt = "F:\\caffe-master170309\\examples\\cifar10\\RecognizeResultRecordFromCmd.txt";// 第二次打开,未解析的RecognizeResultRecordFromCmd.txt文件
						f_RecognizeResultRecordFromCmdTxt_2.open(strAnalysisOfRecognitionFromCmdTxt, std::ios::in);	// 读取已经写好的RecognizeResultRecordFromCmd.txt文件,并解析然后写入另一个AnalysisOfRecognitionfromCmdTxt.txt文件
						if (f_RecognizeResultRecordFromCmdTxt_2)
						{
							std::string OnePicPath;														// 单张图片的路径
							std::string RecognizeAnsOfOnePic;											// 该图片的识别结果
							std::string rubbishTmp;														// 解析:就是将多余的信息去掉
							getline(f_RecognizeResultRecordFromCmdTxt_2, OnePicPath);					// 第一行
							getline(f_RecognizeResultRecordFromCmdTxt_2, RecognizeAnsOfOnePic);			// 第二行
							while (!f_RecognizeResultRecordFromCmdTxt_2.eof())
							{
								for (int i = 0; i < 4; ++i)
									getline(f_RecognizeResultRecordFromCmdTxt_2, rubbishTmp);			// 解析时:中间多余的3行就不要了

								getline(f_RecognizeResultRecordFromCmdTxt_2, OnePicPath);				// 读取单张图片的路径 的那一行
								getline(f_RecognizeResultRecordFromCmdTxt_2, RecognizeAnsOfOnePic);		// 读取该单张图片对应的识别结果 的那一行
								f_AnalysisOfRecognitionFromCmdTxt << OnePicPath << "   " << RecognizeAnsOfOnePic << std::endl;// 两列:图片路径+识别结果
							}

						}


未解析的效果如下:


解析的效果如下:



3. 将上述的解析后的txt输出在界面上

但是不是显示一张图片出一张结果,而是所有图片播放&处理完了之后,才在界面上显示结果。

放在运行第二部:*.bat之后,但无效,如下图:

					// 2. MFC中调用"F:\\caffe-master170309\\Build\\x64\\Debug\\calssfication.bat"程序
					system(strBatPath.c_str());        // http://blog.csdn.net/u011867581/article/details/44161787  // 如果嫌system黑窗口一闪,将system("...")替换为WinExec("cmd /c ...",SW_HIDE);
					// WinExec("""F:\\caffe-master170309\\Build\\x64\\Debug\\calssfication.bat", SW_HIDE);

					/*
					// 3. 读取并解析Caffe测试(识别)的结果(已保存到F:\\caffe-master170309\\examples\\cifar10\\RecognizeResultRecordFromCmdTxt.txt里),并输出到界面Edit2上
					// 在这里无效,显示的太快看不见的原因吧
					std::fstream f_RecognizeResultRecordFromCmdTxt;
					f_RecognizeResultRecordFromCmdTxt.open(strRecognizeResultRecordFromCmdTxt, std::ios::in);
					if (f_RecognizeResultRecordFromCmdTxt)
					{
						std::string OnePicPath;														// 单张图片的路径
						std::string RecognizeAnsOfOnePic;											// 该图片的识别结果
						std::string rubbishTmp;														// 解析:就是将多余的信息去掉

						getline(f_RecognizeResultRecordFromCmdTxt, OnePicPath);						// 第一行: 读取单张图片的路径
						getline(f_RecognizeResultRecordFromCmdTxt, RecognizeAnsOfOnePic);			// 第二行: 读取该单张图片对应的识别结果
						for (int i = 0; i < 4; ++i)													// 跳过4行
							getline(f_RecognizeResultRecordFromCmdTxt, rubbishTmp);					// 解析时:中间多余的4行就不要了
						
						std::string RecgnitionAns = OnePicPath + "   " + RecognizeAnsOfOnePic;		// 两列:图片路径+识别结果
						CEdit* pBox3;
						pBox3 = (CEdit*)GetDlgItem(IDC_EDIT3);
						CString CStrRecordData = CString(RecgnitionAns.c_str());
						pBox3->SetWindowText(CStrRecordData);

						f_RecognizeResultRecordFromCmdTxt.close();
					}







// 4. 找到并读取Caffe测试(识别)的结果(已保存到F:\\caffe-master170309\\examples\\cifar10\\AnalysisOfRecognitionfromCmdTxt.txt里),并输出到界面Edit2上
					// 因为f_AnalysisOfRecognitionFromCmdTxt文件已经走到末尾了,在读也读不出东西了,必须把偏移量指向开头。我这里是关了再重新打开,然后从头读取
					std::fstream fRecord;
					fRecord.open(strAnalysisOfRecognitionFromCmdTxt, std::ios::in);
					if (fRecord)
					{
						std::string recordData;
						std::string line;
						while (getline(fRecord, line))  // http://blog.csdn.net/guowenyan001/article/details/11231927
						{
							std::string s1 = line;
							std::string s2 = std::string("\r\n\n");
							std::string s3 = s1 + s2;
							char *cs3 = const_cast<char*>(s3.c_str());

							recordData += std::string(cs3);
						}

						CEdit* pBox3;
						pBox3 = (CEdit*)GetDlgItem(IDC_EDIT3);
						CString CStrRecordData = CString(recordData.c_str());
						pBox3->SetWindowText(CStrRecordData);
					}




4. 加一个进度条

需要提前遍历一遍,统计文件夹内有多少个png文件totalCnt,然后第二次遍历时,每当有一个png时,cnt++,算出百分比cnt / totalCnt,百分比就是进度条的值。

如下:

					// 3. 进度条
					++pngFilecnt;
					CProgressCtrl *myProCtrl2 = (CProgressCtrl *)GetDlgItem(IDC_PROGRESS1);
					myProCtrl2->SetRange(0, 100);
					double pos = 100 * (pngFilecnt / totalPngFileCnt);						// 因为进度条SetPos函数参数是int,而int/int = int, 故需要将范围设置为(0,100)而不是(0,1)
					myProCtrl2->SetPos(pos);


最终效果如下图:



程序在这:链接:http://pan.baidu.com/s/1kUS03bx 密码:ozrh

20170323,cmd窗口不出现不闪烁的程序:链接: http://pan.baidu.com/s/1i54ynA1

20170324程序,界面上的图片和标签不一同显示。


参考:我的MFC笔记

参考:后台运行bat程序

发表评论

4个评论

  • qq_39683831

    楼主,哪个批处理识别图片后面的网盘失效了。可以再发一次吗?急需啊,谢谢

    2017-08-06 19:06:14回复

  • daska110

    里边的链接失效了,可以看这个。链接:http://pan.baidu.com/s/1nu8MfHn 密码:ru6e

    2017-05-08 08:24:22回复

  • xyxd190

    可以学习下源码吗?

    2017-05-08 01:01:27回复

  • daska110

    回复xyxd190: 里边的链接失效了,可以看这个。链接:http://pan.baidu.com/s/1nu8MfHn 密码:ru6e

    2017-05-08 08:24:34回复

我要留言×

技术领域:

我要留言×

留言成功,我们将在审核后加至投票列表中!

提示x

人工智能开发框架知识库已成功保存至我的图谱现在你可以用它来管理自己的知识内容了

删除图谱提示×

你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?

删除节点提示×

无法删除该知识节点,因该节点下仍保存有相关知识内容!

删除节点提示×

你确定要删除该知识节点吗?