OpenCV 利用Directory类实现文件夹遍历(只适用于2.x版本的opencv)

最近,我在进行新的工作中,需要对多张图片进行测试,一一测试太慢了,于是想到将需要处理的图片放到一个文件夹中,对文件夹中所有图像进行遍历,这样可以省时省力.

参考博客https://blog.csdn.net/watkinsong/article/details/9227439中的内容,我在VS2010中实践了一番:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	std::string dirPath = "E:\\test";	//文件夹路径
	cv::Directory dir;			//文件夹类对象
	std::vector<std::string> fileNames = dir.GetListFiles(dirPath, "*.bmp", false);	//获取文件夹下文件名序列
	for(size_t i = 0; i < fileNames.size(); i++)
	{
		std::string fileName = fileNames[i];			//取出当前文件名
		std::string fileFullPath = dirPath + fileName;	//获取当前文件完整路径
		std::cout << "file name: " << fileName << endl;	//打印当前文件名
		std::cout << "file paht: " << fileFullPath << endl;	//打印当前文件路径
	}
	system("pause");
	return 0;
}

控制台输出如下:

查看一下我测试用的文件夹

结果正确.

虽然得到我想要的结果了,但是觉得有必要大致了解一下用到的类和函数.上述实现主要用到了Directory类的成员函数GetListFiles,

下面简单学习一下,便于以后遇到可以快速使用.

可以看到Directory类存在于opencv中的contrib模块,含有三个成员函数:

(1)static std::vector<std::string> GetListFiles  ( const std::string& path, const std::string & exten = "*", bool addPath = true );

(2)static std::vector<std::string> GetListFilesR ( const std::string& path, const std::string & exten = "*", bool addPath = true );

(3)static std::vector<std::string> GetListFolders( const std::string& path, const std::string & exten = "*", bool addPath = true );

可以看到三个成员函数的返回值都是std::vector<std::string>,输入参数都是const std::string& path, const std::string & exten = "*", bool addPath = true.关于返回值和输入参数,需要结合函数实现加以理解.

在D:\opencv\opencv2410\opencv\sources\modules\contrib\src\inputoutput.cpp中可以看到函数实现

首先看一下GetListFiles函数实现

    std::vector<std::string> Directory::GetListFiles( const std::string& path, const std::string & exten, bool addPath )
    {
        std::vector<std::string> list;
        list.clear();
        std::string path_f = path + "/" + exten;
        #ifdef WIN32
        #ifdef HAVE_WINRT
            WIN32_FIND_DATAW FindFileData;
        #else
            WIN32_FIND_DATAA FindFileData;
        #endif
        HANDLE hFind;

        #ifdef HAVE_WINRT
            wchar_t wpath[MAX_PATH];
            size_t copied = mbstowcs(wpath, path_f.c_str(), MAX_PATH);
            CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
            hFind = FindFirstFileExW(wpath, FindExInfoStandard, &FindFileData, FindExSearchNameMatch, NULL, 0);
        #else
            hFind = FindFirstFileA((LPCSTR)path_f.c_str(), &FindFileData);
        #endif
            if (hFind == INVALID_HANDLE_VALUE)
            {
                return list;
            }
            else
            {
                do
                {
                    if (FindFileData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL  ||
                        FindFileData.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE ||
                        FindFileData.dwFileAttributes == FILE_ATTRIBUTE_HIDDEN  ||
                        FindFileData.dwFileAttributes == FILE_ATTRIBUTE_SYSTEM  ||
                        FindFileData.dwFileAttributes == FILE_ATTRIBUTE_READONLY)
                    {
                        char* fname;
                    #ifdef HAVE_WINRT
                        char fname_tmp[MAX_PATH] = {0};
                        size_t copied = wcstombs(fname_tmp, FindFileData.cFileName, MAX_PATH);
                        CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
                        fname = fname_tmp;
                    #else
                        fname = FindFileData.cFileName;
                    #endif
                        if (addPath)
                            list.push_back(path + "/" + std::string(fname));
                        else
                            list.push_back(std::string(fname));
                    }
                }
            #ifdef HAVE_WINRT
                while(FindNextFileW(hFind, &FindFileData));
            #else
                while(FindNextFileA(hFind, &FindFileData));
            #endif
                FindClose(hFind);
            }
        #else
            (void)addPath;
            DIR *dp;
            struct dirent *dirp;
            if((dp = opendir(path.c_str())) == NULL)
            {
                return list;
            }

            while ((dirp = readdir(dp)) != NULL)
            {
                if (dirp->d_type == DT_REG)
                {
                    if (exten.compare("*") == 0)
                        list.push_back(static_cast<std::string>(dirp->d_name));
                    else
                        if (std::string(dirp->d_name).find(exten) != std::string::npos)
                            list.push_back(static_cast<std::string>(dirp->d_name));
                }
            }
            closedir(dp);
        #endif

        return list;
    }

虽然我不能完全看懂代码,但是可以大概了解返回值和输入参数代表什么.

std::string path_f = path + "/" + exten;这句话可以说明path是输入待遍历的文件夹路径,extern是待遍历的文件的扩展名

if (addPath) 

    list.push_back(path + "/" + std::string(fname));

else

    list.push_back(std::string(fname));

这句if-else判断是根据addPath的值决定返回的list中存放的是文件名还是文件的完整路径

如果addPath是false,则返回的是文件名

如果addPath是True,则返回的是文件完整路径

这一点也就解释了上述实现中使用false所以得到的只是文件的名,得到完整路径还需要自己连接一下.如果改成true,是否真的可以直接得到路径呢?验证一下吧:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	std::string dirPath = "E:\\test";	//文件夹路径
	cv::Directory dir;			//文件夹类对象
	std::vector<std::string> fileNames = dir.GetListFiles(dirPath, "*.bmp", true);	//获取文件夹下文件名序列
	for(size_t i = 0; i < fileNames.size(); i++)
	{
		std::string fileName = fileNames[i];			//取出当前文件名
		//std::string fileFullPath = dirPath + fileName;	//获取当前文件完整路径
		std::cout << "file name: " << fileName << endl;	//打印当前文件名
		//std::cout << "file paht: " << fileFullPath << endl;	//打印当前文件路径
	}
	system("pause");
	return 0;
}

这个路径有点奇怪,前面是\后面是/,然后自习看函数实现,里面用的都是/,因此我也改成/就可以了,改成

std::string dirPath = "E:/test";    //文件夹路径

在运行一下

这样就可以直接返回正常的路径了.

本来还想把函数GetListFolders和函数GetListFilesR好好研究一下,但是时间有点太晚了,得睡觉了,明天还得上班.简单粘贴一下别人博客中的话:

(1)、GetListFiles:遍历指定文件夹下的所有文件,不包括指定文件夹内的文件夹;

(2)、GetListFolders:遍历指定文件夹下的所有文件夹,不包括指定文件夹下的文件;

(3)、GetListFilesR:遍历指定文件夹下的所有文件,包括指定文件夹内的文件夹。

也就是说GetListFilesR是集合了GetListFiles函数和GetListFolders函数的功能,我看了一眼实现,确实如此.这个实现基本一下就能看懂,先遍历文件夹下所有文件(不包括指定文件夹内的文件夹),然后遍历文件夹下所有文件夹(不包括指定文件夹下的文件),最后遍历上一部得到的文件夹下所有文件,这样返回的就是文件夹下所有的文件(包括指定文件夹内的文件夹).

    std::vector<std::string> Directory::GetListFilesR ( const std::string& path, const std::string & exten, bool addPath )
    {
        std::vector<std::string> list = Directory::GetListFiles(path, exten, addPath);

        std::vector<std::string> dirs = Directory::GetListFolders(path, exten, addPath);

        std::vector<std::string>::const_iterator it;
        for (it = dirs.begin(); it != dirs.end(); ++it)
        {
            std::vector<std::string> cl = Directory::GetListFiles(*it, exten, addPath);
            list.insert(list.end(), cl.begin(), cl.end());
        }

        return list;
    }

}

有时间利用这三个函数完成一下文件夹对比功能的实现,之前在github上下了一个python版的实现,看到这三个函数我觉得也可以用opencv实现一下文件夹比对.

 

参考博客:

https://blog.csdn.net/watkinsong/article/details/9227439

https://blog.csdn.net/fengbingchun/article/details/42435901

 

备注:本篇博客只适用于2.x版本的opencv,3版本后该用

CV_EXPORTS void glob(String pattern, std::vector<String>& result, bool recursive = false);

参考博客 https://blog.csdn.net/m_buddy/article/details/86485618

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值