OpenCV学习之例程详解(03):搜索文件夹下所有指定类型图片并逐张显示

有时候我们需要批量载入图片以进行后续处理,而这些图片放置在某个文件夹下,现在来看看如何实现。

浏览文件夹的功能可以参考这篇文章(在MFC中实现“浏览文件夹”功能),本文略去这一步。

作为示例,我们编写Console程序输入文件夹路径,设置扩展名,完整代码(有详细注释)如下

#include <io.h> // _finddata_t结构, _access(), _findfile()等
#include <direct.h> //_chdir()目录操作
#include <iostream>
#include <fstream>
#include <sstream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#pragma comment(lib,"opencv_core249.lib")
#pragma comment(lib,"opencv_highgui249.lib")
using namespace cv;
using namespace std;

// 最多支持50张图片,可根据需要修改(但这个数字不能太大)
#define MAX_COUNT 50

//搜索folder目录下扩展名为ext的文件,将文件完整路径写入fileNames
int TraverseFolder(const string& folder, const string& extension, vector<string>& fileNames);

//载入folder目录下扩展名为ext的图片(数目不超过maxCount),存放在images容器中
int LoadImages(const string& folder, const string& extension, vector<Mat>& images, const int maxCount);

int main(void)
{
	system("COLOR FD");
	string folder, ext = "*.jpg";
	cout << "Folder path:";
	getline(cin, folder); //从输入读取一行
	try
	{
		vector<Mat> images;
		int count=LoadImages(folder, ext, images, MAX_COUNT);
		string windowName = "Display";
		namedWindow(windowName, WINDOW_NORMAL);
		resizeWindow(windowName, 800, 600);
		char text[16] = { 0 };
		for (int idx = 0; idx < count; ++idx)
		{
			//Mat的重载'='只是浅拷贝(引用方式)
			Mat currentImage = images[idx];
			sprintf_s(text, "%02d/%d", idx + 1, count); 
			// 显示文字:“当前/总数”
			putText(currentImage, string(text), cvPoint(10, 50), CV_FONT_BLACK, 1, cvScalar(255));
			imshow(windowName, currentImage);

			//等待用户按键,持续2000毫秒
			//若在这段时间内按下按键则执行后续步骤(循环++i)
			int key = waitKey(2000);
			//用户按键ESC(ASCII码值27)则跳出循环
			if (key == 27) break; 
		}
		destroyAllWindows();
	}
	catch (exception except)
	{
		//捕获到异常,打印异常消息
		cout << except.what() << endl;
	}
	cout << "Press any key to continue...";
	cin.get(); // 类似于_getch()
	return 0;
}

int TraverseFolder(const string& folder, const string& extension, vector<string>& fileNames)
{
	string dir = folder;
	if (_access(dir.c_str(), 06) == -1)
	{
		// 抛出异常 throw(exception)
		// 异常(exception)构造函数的重在版本 exception(const char* const)
		// 语句(dir + ": Path does not exist!")返回一个string对象
		// string::c_str()返回const char*
		throw exception((dir + ": Path does not exist!").c_str());
	}
	if (dir.at(dir.length() - 1) != '\\')
	{
		// 路径字符串不是以'\'结尾的,补上'\'
		dir += '\\';
	}
	if (_chdir(dir.c_str()) != 0)
	{
		// 切换到dir路径
		throw exception(("Error in _chdir:" + dir).c_str());
	}

	string ext = extension;
	if (ext.substr(0, 2) != "*.")
	{
		//扩展名不是'*.xx'形式的补全为该形式
		ext.insert(0, "*.");
	}

	//
	// 查找文件
	_finddata_t  findData;
	memset(&findData, 0x0, sizeof(findData));
	int findHandle = _findfirst(ext.c_str(), &findData);
	if (findHandle == -1)
	{
		throw exception("Failed in function: \'_findfirst\'");
	}
	int result=0, count = 0;
	do
	{
		fileNames.push_back(dir + findData.name);
		++count;
		result = _findnext(findHandle, &findData);
	} while (result == 0);

	_findclose(findHandle);
	//查找完成
	//

	return count;
}

int LoadImages(const string& folder, const string& extension, vector<Mat>& images, const int maxCount = 20)
{
	vector<string> fileNames;
	int count = TraverseFolder(folder, extension, fileNames);
	if (count == 0)
	{
		throw exception("No image found");
	}

	count = (count < maxCount) ? count : maxCount;
	for (int i = 0; i < count; ++i)
	{
		images.push_back(imread(fileNames[i], CV_LOAD_IMAGE_UNCHANGED));
		cout << fileNames[i] << " ...loaded." << endl;
	}
	cout << "Loaded "<<count << " image(s)" << endl;
	return count;
}

显示图片部分的代码可以从这篇文章(OpenCV学习之例程详解(01):HelloWorld)里找到影子。

当然,还有几种替代方案,其一就是事先生成文件列表然后从列表文件中读取文件路径,效果大同小异,

这里也贴出来吧。先编写bat文件(假设图片存放在F:\Image\test文件夹下)并保存

@cls
@rem @dir F:\Image\test  /s /b  >F:\Image\test_imgs.csv
@pause
执行上述命令,然后实现LoadImages函数模块

#include <iostream>
#include <fstream>
#include <sstream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#pragma comment(lib,"opencv_core249.lib")
#pragma comment(lib,"opencv_highgui249.lib")
using namespace cv;
using namespace std;

static void LoadImages(const string& filename, vector<Mat>& images)
{
    ifstream file(filename, ifstream::in);
	assert(file.is_open());
    string line;
    while (getline(file, line))
	{
        images.push_back(imread(line, CV_LOAD_IMAGE_UNCHANGED));
    }
}
在主函数中类似下述方式载入图片(代码片段):

    try
	{
		string imgListFile;
		cout << "请输入列表文件名(*.csv文件):";
		cin >> imgListFile; // F:/Image/test_imgs.csv
		vector<Mat> images;
        LoadImages(imgListFile, images);
		assert(images.size() > 1);
		//...
	}
	catch(..)
剩余部分与前文一致。

本文示例的运行结果截图如下




点此领取楼主


转载于:https://www.cnblogs.com/fengyhack/p/10603731.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值