Linux&C++以時間批量重命名圖片數據集

題目來源於計算機視覺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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章