美文网首页OpenCV实战OpenCV与深度学习软件开发
如何遍历文件夹下的所有图片(Pyhton&C++)

如何遍历文件夹下的所有图片(Pyhton&C++)

作者: 冰不语 | 来源:发表于2017-05-22 18:39 被阅读539次

    前言

    虽然本文说的是遍历图片,但是遍历其他文件也是可以的。

    在进行图像处理的时候,大部分时候只需要处理单张图片。但是一旦把图像处理和机器学习相结合,或者做一些稍大一些的任务的时候,常常需要处理好多图片。而这里面,一个最基本的问题就是如何遍历这些图片。

    用opencv做过人脸识别的人应该知道,那个项目中并没有进行图片的遍历,而是用了一种辅助方案,生成了一个包含所有图片路径的文件at.txt,然后通过这个路径来读取所有图片。而且这个辅助文件不仅包含了图片的路径,还包含了图片对应的标签。所以在进行训练的时候直接通过这个辅助文件来读取训练用的图片和标签。

    其实如果去看看教程,会发现这个at.txt的生成是通过Python代码来实现。所以今天就来看一下如何用C++来实现文件夹下所有图片的遍历。

    当然在此之前还是先给出Python遍历的代码,以备后用。

    Python遍历

    在之前的数独项目中,进行图像处理的时候用到了遍历文件夹下所有的图片。主要是利用glob模块。glob是python自己带的一个文件操作相关模块,内容不多,可以用它查找符合自己目的的文件。

    # encoding: UTF-8
    import glob as gb
    import cv2
    
    #Returns a list of all folders with participant numbers
    img_path = gb.glob("numbers\\*.jpg") 
    for path in img_path:
        img  = cv2.imread(path) 
        cv2.imshow('img',img)
        cv2.waitKey(1000)
    

    C++遍历

    1. opencv自带函数glob()遍历

    OpenCV自带一个函数glob()可以遍历文件,如果用这个函数的话,遍历文件也是非常简单的。这个函数非常强大,人脸识别的时候用这个函数应该会比用at.txt更加方便。一个参考示例如下。

    #include<opencv2\opencv.hpp>
    #include<iostream>
    
    using namespace std;
    using namespace cv;
    
    vector<Mat> read_images_in_folder(cv::String pattern);
    
    int main()
    {
        cv::String pattern = "G:/temp_picture/*.jpg";
        vector<Mat> images = read_images_in_folder(pattern);
    
        return 0;   
    }
    
    vector<Mat> read_images_in_folder(cv::String pattern)
    {
        vector<cv::String> fn;
        glob(pattern, fn, false);
    
        vector<Mat> images;
        size_t count = fn.size(); //number of png files in images folder
        for (size_t i = 0; i < count; i++)
        {
            images.push_back(imread(fn[i]));
            imshow("img", imread(fn[i]));
            waitKey(1000);
        }
        return images;
    }
    

    需要注意的是,这里的路径和模式都用的是cv::String

    2. 自己写一个遍历文件夹的函数

    在windows下,没有dirent.h可用,但是可以根据windows.h自己写一个遍历函数。这就有点像是上面的glob的原理和实现了。

    #include<opencv2\opencv.hpp>
    #include<iostream>
    #include <windows.h> // for windows systems
    
    using namespace std;
    using namespace cv;
    
    void read_files(std::vector<string> &filepaths,std::vector<string> &filenames, const string &directory);
    
    int main()
    {
        string folder = "G:/temp_picture/";
        vector<string> filepaths,filenames;
        read_files(filepaths,filenames, folder);
        for (size_t i = 0; i < filepaths.size(); ++i)
        {
            //Mat src = imread(filepaths[i]);
            Mat src = imread(folder + filenames[i]);
            if (!src.data)
                cerr << "Problem loading image!!!" << endl;
            imshow(filenames[i], src);
            waitKey(1000);
        }
        return 0;
            
    }
    
    void read_files(std::vector<string> &filepaths, std::vector<string> &filenames, const string &directory)
    {
        HANDLE dir;
        WIN32_FIND_DATA file_data;
    
        if ((dir = FindFirstFile((directory + "/*").c_str(), &file_data)) == INVALID_HANDLE_VALUE)
            return; /* No files found */
    
        do {
            const string file_name = file_data.cFileName;
            const string file_path = directory + "/" + file_name;
            const bool is_directory = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
    
            if (file_name[0] == '.')
                continue;
    
            if (is_directory)
                continue;
    
            filepaths.push_back(file_path);
            filenames.push_back(file_name);
        } while (FindNextFile(dir, &file_data));
    
        FindClose(dir);
    } 
    

    3. 基于Boost

    如果电脑上配置了boost库,用boost库来实现这一功能也是比较简洁的。为了用这个我还专门完全编译了Boost。

    然而只用到了filesystem。

    #include <boost/filesystem.hpp>
    #include<iostream>
    #include<opencv2\opencv.hpp>
    
    using namespace cv;
    using namespace std;
    using namespace boost::filesystem;
    
    void readFilenamesBoost(vector<string> &filenames, const string &folder);
    
    int main()
    {
        string folder = "G:/temp_picture/";
        vector<string> filenames;
        readFilenamesBoost(filenames, folder);
        for (size_t i = 0; i < filenames.size(); ++i)
        {
            Mat src = imread(folder + filenames[i]);
    
            if (!src.data)
                cerr << "Problem loading image!!!" << endl;
            imshow("img", src);
            waitKey(1000);
        }
        return 0;
    }
    
    void readFilenamesBoost(vector<string> &filenames, const string &folder)
    {
        path directory(folder);
        directory_iterator itr(directory), end_itr;
        string current_file = itr->path().string();
    
        for (; itr != end_itr; ++itr)
        {
            if (is_regular_file(itr->path()))
            {
                string filename = itr->path().filename().string(); // returns just filename
                filenames.push_back(filename);
            }
        }
    }
    

    各种方法都记录在这里,以便以后用的时候查找。


    公众号CVPy,分享OpenCV和Python的实战内容。每一篇都会放出完整的代码。欢迎关注。
    

    相关文章

      网友评论

      • 古柳_Deserts_X:爬了很多图片,不知道通过opencv或其他方式,怎么找出相似图片,或含猫等某一元素的照片,将其筛选出来
        冰不语:@Deserts_X 这个,工程量确实巨大,但是好像不遍历也没有其他办法。。。用Python可能会更简单一点,但是工程量仍然巨大,这是免不了的。。。反正这样的工程量我的小本本hold不住:joy:
        古柳_Deserts_X:@冰不语 哎。感觉遍历的方式都会很麻烦,一个文件夹里6K+照片,近200个文件夹,约400GB,想想有点hold不住
        冰不语:相似图片可以用一些相似性度量的方法,比如对比直方图或者特征向量之类的,如果要找出含有某一类元素的,就需要目标检测了。OpenCV自带的有猫脸检测的分类器,只能检测猫的正脸。

      本文标题:如何遍历文件夹下的所有图片(Pyhton&C++)

      本文链接:https://www.haomeiwen.com/subject/mjdixxtx.html