题目来源于计算机视觉life从零开始学SLAM作业1。我们知道,SLAM与SFM不同,SLAM是按时间序列来处理图像。所以,当我们有一个数据集且要把它用到我们的SLAM系统中,有时候数据集的命名方式可能不太友好,比如TUM的RGBD数据集中的RGB数据,是以时间命名的,为了能够把该数据集用到我们的系统上,而且又想比较方便地读取图片,我们可以批量重命名这些图像数据。(实际上,有更好的方法,用c艹实在是太笨拙了)
实际上如果是只想简单地将图片赋值为0.png、1.png…是不需要靠编程就可以实现的,见此链接。
那如果用编程实现呢?有两种思路,一种是由于TUM数据集是以时间来命名的,所以可以直接把名字转换成double类型、排序最后遍历改名。第二种思路是根据修改时间来,我觉得这个会更加靠谱,因为不是所有数据集都是以时间(数字)来命名,根据修改时间来排序,岂不是更好?实际上,是我too toung too naive,由于采集时间之密集,time_t存储的时间位数不足以区分两张图像。
总体思路:于是先遍历当前文件夹的所有文件,然后把名字提取出来,把string类型的名字和long类型的时间,存进map<string,long>里,后续把map转成pair类型的vector,用sort()函数排序,最后遍历所有数,使用rename改名。
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <map>
#include <algorithm>
#include <vector>
using namespace std;
map<string,long> mymap;
int num = 0;
struct cmp
{
bool operator()(const pair<string,long> &p1,const pair<string,long> &p2)
{
return p1.second < p2.second;
}
};
// 递归列出所有目录及文件
void scan_all_image(char *dir)
{
DIR *p_dir = NULL;
struct dirent *p_entry = NULL;
struct stat statbuf;
if((p_dir = opendir(dir)) == NULL)
{
printf("can't open dir.\n");
return;
}
chdir (dir);
int skip_two = 2; //需要跳过"."和".."文件
while(NULL != (p_entry = readdir(p_dir))) { // 获取下一级目录信息
lstat(p_entry->d_name, &statbuf); // 获取下一级成员属性
//先跳过"."和".."文件
if(skip_two != 0)
{
skip_two --;
continue;
}
//输出信息
//第一种方法:以修改时间排序 在这里不可行,精度不够,但是在时间相隔较大的图片中,是ok的
// cout <<"image name: " << p_entry->d_name << " " << "modify_time : " <<long_modify_time << endl;
// mymap[p_entry->d_name] = long_modify_time;//存进map里
string img_nam = p_entry->d_name;
string img_cut = img_nam.substr(8, 9); //截取s中从pos开始(包括0)的n个字符的子串,并返回
cout <<img_cut << endl;
long image_name = (long)(atof(img_cut.c_str()) * 1000000);
//第二种方法:以名字排序
cout <<"image name: " << p_entry->d_name << " " << "time : " <<image_name << endl;
mymap[p_entry->d_name] = image_name;//存进map里
}
chdir(".."); // 回到上级目录
closedir(p_dir);
}
int rename_all_image(string argv)
{
vector<pair<string,long>>vect(mymap.begin(),mymap.end()); //把map打包成vector,方便后面用sort排序
sort(vect.begin(),vect.end(),cmp()); //排序
for(vector<pair<string,long>>::iterator it = vect.begin(); it != vect.end(); it ++)//遍历所有文件
{
cout <<"map time : " << it->second << endl;
string new_name = argv + to_string(num) + ".png";
string old_name = argv + it->first;
cout << "old name :" << it->first << " new name :" << to_string(num) + ".png" << endl;
if (!rename(old_name.c_str(), new_name.c_str()))//使用rename改名
{
std::cout << "rename success "<< std::endl;
}
else
{
std::cout << "rename error "<< std::endl;
}
num++;
}
}
int main(int argc, char* argv[])
{
scan_all_image(argv[1]); //发现所有文件,并存入map
rename_all_image(argv[1]); //重命名所有图像
return 0;
}
效果如下,挺妥。
参考:
https://blog.csdn.net/huangjiazhi_/article/details/80501233
https://www.cnblogs.com/achao123456/p/9676524.html