1 はじめに
学生時代はOpenCVを使って画像処理系の研究をしており、そのときに作成したC++の関数を共有します。
また、C++でフォルダ以下にあるファイル一覧を取得する方法は以下のQiitaに書いていますので、そちらを参照ください。
[C++でフォルダ以下にあるファイル一覧を取得する][1]
[1]:https://qiita.com/tes2840/items/8d295b1caaf10eaf33ad
環境:Visual Studio 2017
2 やりたいこと
フォルダ以下にあるファイル一覧を取得し、同じグループの画像(ファイル名で判別)を配列にまとめたい。
3 ソースコード
GroupingImage.cpp
# define SAME_GROUP 0 /* 同じグループ(memcmpで文字列一致した) */
/**
* @brief フォルダ以下の同じグループの画像をまとめる関数
* 画像の命名規則: xx.yy.拡張子(xxを同じグループの場合は同一にする)
* @param[in] folderPath フォルダパス
* @param[out] fileGroups 同じグループの画像をまとめた配列
* @return true:成功, false:失敗
* @detail
*/
bool getImageGroups(std::string folderPath, std::vector< std::vector<std::string> >& imageGroups)
{
bool result = false; /* 処理結果 */
std::vector<std::string> fileNames; /* フォルダ内にあるファイル一覧 */
/* フォルダパス以下にあるファイル一覧を取得する */
result = getFileNames(folderPath, fileNames);
/* ファイル一覧の取得に失敗した場合はfalseを返す */
if (result == false) {
return false;
}
/* ファイル一覧から同じグループのファイルを動的配列にまとめる
* 画像の命名規則: xx.yy.拡張子とし、xxを判別用パスとする
* 判別用パスが同一なら同じグループの画像である
*/
const std::string distinction = "."; /* 判別用文字 */
std::vector<std::string>::iterator it = fileNames.begin();
while (it != fileNames.end()){
std::vector<std::string> sameImageGroup; /* 同じ画像のグループ */
std::string searchStr = *it; /* 判別する画像のパス */
size_t searchStrPos = 0; /* 判別用文字の位置 */
/*配列の先頭の画像をグループに追加し、追加した画像はファイル一覧から削除する */
sameImageGroup.push_back(*it);
it = fileNames.erase(it);
/* 判別用文字の位置を取得する */
searchStrPos = searchStr.find(distinction);
/* ファイル一覧から同じグループのものを取得する */
std::vector<std::string>::iterator tempIt = it;
while (tempIt != fileNames.end()){
int result = std::memcmp(searchStr.c_str(), tempIt->c_str(), searchStrPos);
if (result == SAME_GROUP){
/* 同じグループの画像を配列に追加し、ファイル一覧から削除する */
sameImageGroup.push_back(*tempIt);
tempIt = fileNames.erase(tempIt);
/* すでに削除しているイテレータを参照しているため更新する */
it = tempIt;
}
else{
/* 同じグループでない場合はイテレータを進める */
tempIt++;
}
}
/* グループを追加する */
imageGroups.push_back(sameImageGroup);
}
return true;
}
/**
* @brief フォルダ以下のファイル一覧を取得する関数
* @param[in] folderPath フォルダパス
* @param[out] fileNames ファイル名一覧
* return true:成功, false:失敗
*/
bool getFileNames(std::string folderPath, std::vector<std::string> &fileNames)
{
using namespace std::filesystem;
directory_iterator iter(folderPath), end;
std::error_code err;
for (; iter != end && !err; iter.increment(err)){
const directory_entry entry = *iter;
fileNames.push_back( entry.path().string() );
printf("%s\n", fileNames.back().c_str());
}
/* エラー処理 */
if (err){
std::cout << err.value() << std::endl;
std::cout << err.message() << std::endl;
return false;
}
return true;
}