在tensorflow数据集制作过程中,标记后的数据通常和样本在同一路径下。
在标记数据中,有一列数据为图片路径,一般保存为相对路径形式:即相对于图片所在目录的路径;然而,通过Matlab直接保存的为绝对路径,因此需要转换。
为什么要保存成相对路径呢?
- 比如共享的数据集,被转移路径后,绝对路径会发生变化,需要重新生成CSV文件,很麻烦;
- 而且保存在同一路径下,相对路径在读取图片时候,也比较节省时间。
我们分析一下绝对路径的格式:
诸如:
D:/pictures/labels/group_1/img_23.jpg
在进入图像路径后,直接遍历这个路径下的所有图片。
所以只要保存以下格式:
img_23.jpg
所以问题转化为:截取绝对路径中最后一个反斜杠之后的数据。
处理思路
在被一个大神点播之后,提出以下思路:
- 路径对应的字符串倒序排布;
- 遍历倒序后字符串,并将其保存在另一个字符串,第一次遇到反斜杠就终止;
- 将保存的字符串倒序,即可得到不含路径的图片名称。
CSV中绝对路径批量处理
CSV格式跟excel差不多,只不过一个是表格保存,一个是通过逗号间隔每个字符串。笔者路径在第一列,这个可以根据具体情况选择位置。
批量处理其实需要读写文件,流程如下:
-
读文件:以读的方式打开CSV文件,按行读取字符,并将其保存,可用vector<vector>格式保存;
-
改文件:寻找到filename所在的列,可以直接阅读文件,或者通过vector的find函数定位;
注意:CSV文件第一行为文件头,需要特殊处理,在修改时不进行操作。
-
写文件:将修改后的数据按序写入源文件。
注意:以写的方式打开文件时,源文件数据清空;不过没关系,我们已经将数据保存在内存。
经过这样的处理,绝对路径相对路径灵活运用,若是遇到行列参数编写序号不合tensorflow格式的,也可以通过这种方式。
实际效果如下:
实际操作时候,我把改数据和写文件放在一个流程。
板块复制粘贴功能暂时失效,代码如下:
//字符串倒序操作
void reverseString(string & str)
{
int i = 0, j = str.length() - 1;
while (i < j)
{
std::swap(str[i++], str[j--]);
}
}
//绝对路径改为相对路径
void Path_Absolute_Relative(string &absolutepath,string &relativepath)
{
char line_1[] ="/" ;
char line_2[] = "//";
char line_3[] = "\\";
char *outpath = new char[10];
reverseString(absolutepath);//绝对路径倒序
for (int i = 0; i < absolutepath.length();i++ )
{
if ((absolutepath[i] != line_1[0]) && (absolutepath[i] != line_2[0]) && (absolutepath[i] != line_3[0]))
{
outpath[i] = absolutepath[i];//将倒序后绝对路径反斜杠前的字符保存到相对路径
}
else
{
outpath[i] = '\0';
break;
}
}
relativepath = outpath;
reverseString(relativepath);//相对路径倒序
}
//运行主函数
int main()
{
ifstream fin("D:/boat.csv"); //打开文件流操作,改成自己的CSV文件路径
string line;
vector<vector<string>> datafromfile;
// 读文件,将文件数据保存到本地
while (getline(fin, line)) //整行读取,换行符“\n”区分,遇到文件尾标志eof终止读取
{
istringstream sin(line); //将整行字符串line读入到字符串流istringstream中
vector<string> fields; //声明一个字符串向量
string field;
while (getline(sin, field, ',')) //将字符串流sin中的字符读入到field字符串中,以逗号为分隔符
{
fields.push_back(field); //将刚刚读取的字符串添加到向量fields中
}
datafromfile.push_back(fields);
}
//关闭文件
fin.close();
//写文件形式打开,此时文件被清空,数据保存在本地
ofstream file("D:/boat.csv");
for (int i = 0; i < datafromfile.size(); i++)
{
if (i != 0)
{
string relativepath;
//改写文件名,将绝对路径只保存文件名称
//如果改成相对路径,只需要写字符串和参照路径对比,保存差异部分,即为相对路径
//第一行为文件头,不做修改
//此处操作可以CSV行列调序一类
Path_Absolute_Relative(datafromfile[i][0], relativepath);
datafromfile[i][0] = relativepath;
}
//将数据写入文件
for (int j = 0; j < datafromfile[i].size()-1; j++)
{
file << datafromfile[i][j] << ",";
}
int end = datafromfile[i].size() -1;//最后一位特殊处理
file << datafromfile[i][end] << endl;
}
file.close();
}
代码大概这样,C++写的,还没尝试Matlab写。