目的:
对于做SLAM也好,还是做深度学习也好,涉及到大量的数据,系统对数据处理的时候,需要对比较规范的数据格式进行处理,往往我们提取的图像数据命名并不是那么规范,因此需要对采集的图像信息规范命名。
以python2为例:
本来我提取的数据为按照时间戳作为图像名保存的图像序列,现在想把它改成按照 000000.png 000001.png ...
这样的形式进行处理,这样就可以进行类似kitti的形式跑这个数据集。
方法
# -*- coding:utf8 -*-
import os
class BatchRename():
'''
批量重命名文件夹中的图片文件
'''
def __init__(self):
self.path = '/home/andy/data/kitti_test'
def rename(self):
filelist = os.listdir(self.path)
total_num = len(filelist)
i = 0
for item in filelist:
if item.endswith('.png'):
src = os.path.join(os.path.abspath(self.path), item)
dst = os.path.join(os.path.abspath(self.path), str(i).zfill(6) + '.png')
# 上句是核心,如果仅仅是想命名为按照顺序的图像,比如1.png,2.png,那就改成下面的形式
# dst = os.path.join(os.path.abspath(self.path), str(i) + '.png')
try:
os.rename(src, dst)
print 'converting %s to %s ...' % (src, dst)
i = i + 1
except:
continue
print 'total %d to rename & converted %d jpgs' % (total_num, i)
if __name__ == '__main__':
demo = BatchRename()
demo.rename()
出现的问题:
对原本的数据命名的时候,并没有按照其原先排列的顺序进行命名,这让我感到很懵逼…暂时没有解决这个问题。
解决方案:
用python没能解决上述问题,主要是不知道这里面的机制是什么。下面使用c++的方式进行rename:
#include <iostream>
#include <io.h> //对系统文件进行操作的头文件
#include <string>
#include <sstream>
#include <vector>
using namespace std;
const int N = 6; //整型格式化输出为字符串后的长度,例如,N=6,则整型转为长度为6的字符串,12转为为000012
const string FileType = ".png"; // 需要查找的文件类型,注意修改
/* 函数说明 整型转固定格式的字符串
输入:
n 需要输出的字符串长度
i 需要结构化的整型
输出:
返回转化后的字符串
*/
string int2string(int n, int i)
{
char s[BUFSIZ];
sprintf(s, "%d", i);
int l = strlen(s); // 整型的位数
if (l > n)
{
cout << "整型的长度大于需要格式化的字符串长度!";
}
else
{
stringstream M_num;
for (int i = 0; i < n - l; i++)
M_num << "0";
M_num << i;
return M_num.str();
}
}
int main()
{
_finddata_t c_file; // 查找文件的类
string File_Directory = "D:\\data\\src"; //文件夹目录,注意使用的是双斜杠
string buffer = File_Directory + "\\*" + FileType;
//long hFile; //win7系统,_findnext()返回类型可以是long型
intptr_t hFile; //win10系统 ,_findnext()返回类型为intptr_t ,不能是long型
hFile = _findfirst(buffer.c_str(), &c_file); //找第一个文件
if (hFile == -1L) // 检查文件夹目录下存在需要查找的文件
printf("No %s files in current directory!\n", FileType);
else
{
printf("Listing of files:\n");
int i = 0;
string newfullFilePath;
string oldfullFilePath;
string str_name;
do
{
oldfullFilePath.clear();
newfullFilePath.clear();
str_name.clear();
//旧名字
oldfullFilePath = File_Directory + "\\" + c_file.name;
//新名字
//++i; //从000001.png开始,如果需要取消注释
str_name = int2string(N, i); //整型转字符串
++i;//从 000000.png开始,如果需要从000001.png,则注释这行,取消上面注释
newfullFilePath = File_Directory + "\\" + str_name + FileType;
/*重命名函数rename(const char* _OldFileName,const char* _NewFileName)
第一个参数为旧文件路径,第二个参数为新文件路径*/
int c = rename(oldfullFilePath.c_str(), newfullFilePath.c_str());
if (c == 0)
puts("File successfully renamed");
else
perror("Error renaming file");
} while (_findnext(hFile, &c_file) == 0); //如果找到下个文件的名字成功的话就返回0,否则返回-1
_findclose(hFile);
}
return 0;
}
把图像名保存到txt
如果想把所有图像的名字保存到txt中,那就使用下面的方式:
# -*- coding:utf8 -*-
import os
f = open('/home/andy/a.txt','w')#改成你想保存的txt的路径及名字
for root, dirs, files, in os.walk('/home/andy/rgb',True):
for file in files:
f.writelines(file)
f.write('\n')
至于这步,是有个缺陷的,那就是具有随机性,而不具有顺序性,你会发现你保存的txt里面的名字和你的图像序列并不是对应的,txt的文件名顺序不符合原来的图像顺序,是随机的。不知道是否满足你的需求,我的方法是由于我是按照时间戳命名的,那我就按时间对这个txt进行升序操作就可以了。方法是使用notepad++,一步就解决问题。