C++
和opencv
下遍历文件夹下所有图片并保存的方法
第一种方式:采用glob
函数
- 将图片名按顺序修改为0000,0001,0002等。
- 采用
Opencv
中glob
函数获取文件路径,参考以下链 - 注意点:
- 此方法无需知道文件夹中图片数量
- 文件夹路径采用双斜杠\分开,并且最后的双斜杠不要忘记
附上代码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
-
sprintf_s
()是sprintf
()的安全版本,通过指定缓冲区长度来避免sprintf
()存在的溢出风险 -
sprintf
参考```
附上代码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;
}
}
第三种方式:无需修改图片文件名
- 此种方法参考其他文章,修改后可实现读取文件夹下所有图片进行处理后并以相同图片名称进行保存
- 参考链接:
附上代码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;
}