C++ 和opencv 下遍历文件夹下所有图片并保存的方法

C++opencv 下遍历文件夹下所有图片并保存的方法

第一种方式:采用glob函数
  1. 将图片名按顺序修改为0000,0001,0002等。
  2. 采用Opencvglob函数获取文件路径,参考以下链https://blog.csdn.net/GeorgeAI/article/details/81035422
  3. 注意点:
  • 此方法无需知道文件夹中图片数量
  • 文件夹路径采用双斜杠\分开,并且最后的双斜杠不要忘记

附上代码1:

//头文件 VS2019编译环境
#include <iostream>
#include <vector>
#include <io.h>
#include <string>
#include <cstdio>
#include <opencv2/opencv.hpp>
#include<stdio.h>
#include < fstream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
using namespace cv;
/*修改文件夹中图片文件名为0000-0001-......格式并保存至另一文件夹*/
int main(int argc, char** argv)
{
    string path = "I:\\Multest_2_1\\";//此处替换为自己的图片序列
    string write_path = "I:\\Multest_2_1\\";//目标文件夹,需要提前建好
    vector<String> src_name;
    glob(path, src_name, false);//调用opncv中的glob函数,将遍历路径path,将该路径下的全部文件名的绝对路径存进src_name,如/home/chuyi/xingqiu/homework/homework1/rgb/001.png
    if (src_name.size() == 0)
    {
        cerr << "That's no file in " << path << endl;
        exit(1);
    }
    for (int i = 0; i < src_name.size(); ++i)
    {
        Mat image = imread(src_name[i]);
        if (image.empty())
        {
            cerr << "Read image " << src_name[i] << " failed!";
            exit(1);
        }
        //imshow("test", image);
        //waitKey(0);
        string new_name = write_path + format("/%04d", i) + ".jpg";//控制输出为4位整数并在前面补0
        //cout << new_name <<endl;
        imwrite(new_name, image);
        if (remove(src_name[i].c_str()))//删除源图片
        {
            cerr << "Delete " << src_name[i] << " failed" << endl;
        }
        cout << "Renaming " << src_name[i] << " to " << new_name << endl;
    }
    cout << "Totally rename " << src_name.size() << " pictures!" << endl;
    return 0;
}
第二种方式:采用sprintf_S
  1. sprintf_s()是sprintf()的安全版本,通过指定缓冲区长度来避免sprintf()存在的溢出风险
  2. sprintf参考``https://blog.csdn.net/yishizuofei/article/details/78195255`

附上代码2:

// sprintf_s 方式
/*  这种遍历文件夹中图片的方式需要提前将图片重新命名  */
int main()
{
    char input_filename[255];   //定义一个256个字节大小字符类型input_filename用来存储每次的文件名
    char output_filename[255];
    int file_numbeers = 24;    //文件夹中图片的个数
    for (int i = 1; i <= file_numbeers; i++)
    {
        //input中有24个文件
        sprintf_s(input_filename, "%s\\%d.jpg", "I:\\Multest_2_1\\", i);
        Mat image = imread(input_filename);
        Mat imageGray;
        if (image.channels() == 3)
        {
            cvtColor(image, imageGray, CV_BGR2GRAY);
        }
        else
        {
            image.copyTo(imageGray);
        }
        //imshow("img", imageGray);
        Mat res;
        resize(image, res, Size(imageGray.cols/4, imageGray.rows/4),INTER_NEAREST);
        //输出
        sprintf_s(output_filename, "%s\\%d.jpg", "I:\\Multest_2_1_temp\\", i);
        imwrite(output_filename, res);
        cout << "resize完成第" << i << "张照片" << endl;
    }

}
第三种方式:无需修改图片文件名
  1. 此种方法参考其他文章,修改后可实现读取文件夹下所有图片进行处理后并以相同图片名称进行保存
  2. 参考链接:https://blog.csdn.net/duiwangxiaomi/article/details/88911917

附上代码3:

//读入指定文件夹下的所有文件
void getFiles(string path, vector<string>& files,vector<string>& filenames)
{
    intptr_t   hFile = 0;//intptr_t和uintptr_t是什么类型:typedef long int/ typedef unsigned long int
    struct _finddata_t fileinfo;
    string p;
    //assign方法可以理解为先将原字符串清空,然后赋予新的值作替换。
    if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1) 
    {
        do
        {
            if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
                //这句有点不明白,如果不加,识别的文件里就有.和..两个文件,哪位大神可以给解释下?感激不尽!!!
            {
                files.push_back(p.assign(path).append("\\").append(fileinfo.name));
                filenames.push_back(fileinfo.name);
            }

        } while (_findnext(hFile, &fileinfo) == 0);
        _findclose(hFile);
    }
}
//调用
int main()
{
    char windowname[10];
    string filePath = "I:\\Multest_2_1\\";          //源文件夹
    string dst_filePath = "I:\\Multest_2_1_temp\\"; //目标文件夹
    vector<string> files;
    vector<string> filenames;

    getFiles(filePath, files, filenames);

    int number = files.size();//文件数量
    for (int i = 0; i < number; i++)
    {
        string saveFilename =  dst_filePath + filenames[i];  //写入部分
        Mat img = imread(files[i]);
        imwrite(saveFilename, img);                         //以相同文件名保存至另外一个文件夹
        // imshow显示
        //sprintf_s(windowname, "%d_picture", i);
        //imshow(windowname, img);
        //waitKey(1000);
        //cvDestroyAllWindows();
    }
    cout << "处理完" << files.size() << "张图片" << endl;
}

期间有参考其他文章和帖子:,链接如下:

  • https://www.cnblogs.com/long5683/p/11192546.html
  • https://blog.csdn.net/weixin_39583302/article/details/105725600?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.control
  • 7
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用OpenCV遍历指定中文路径下的图片时,需要注意以下几点: 1. 确保操作系统的编码方式与代码中的编码方式一致。一般情况下,Windows操作系统的默认编码方式是GBK,而OpenCV默认使用UTF-8编码。因此,在代码中需要将路径字符串使用正确的编码方式进行解码,以确保路径能够被正确识别。 2. 使用正确的路径分隔符。在Windows操作系统中,路径分隔符为"\",而在Linux和Mac OS中为"/"。在代码中,根据不同的操作系统选择合适的路径分隔符。 3. 使用递归的方式遍历文件夹中的所有图片。可以使用递归函数来实现文件夹遍历,对于每个遍历到的文件,判断其后缀名是否为图片格式(如.jpg、.png等),如果是图片则进行相应的处理。 下面是一个简单的示例代码: ``` import os import cv2 # 遍历文件夹中的所有图片 def traverse_images(folder_path): # 获取文件夹中的所有文件和文件夹 for file_name in os.listdir(folder_path): # 获取文件的完整路径 file_path = os.path.join(folder_path, file_name) # 判断是否是文件夹 if os.path.isdir(file_path): # 若是文件夹,则递归遍历 traverse_images(file_path) else: # 若是文件,则判断是否为图片格式 if file_path.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp')): # 使用OpenCV读取图片 image = cv2.imread(file_path) # 进行相应的处理,例如显示、保存等 # 指定中文路径 folder_path = '中文路径' # 解码路径字符串 folder_path = folder_path.encode('utf-8').decode('gbk') # 遍历指定路径下的图片 traverse_images(folder_path) ``` 以上代码是一个简单的示例,根据实际需求可以进行相应的扩展和修改。注意根据自己的操作系统和编码方式进行适当的调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值