绪论
本文记录 Windows 下 C++ 利用 OpenCv glob 函数得到 文件夹下所有文件的绝对路径(含文件名)。本文还含有 std::string::find()等函数的记录。如果是 Python 就很简单了。但是 C++还是不简单的。
#include <opencv2/opencv.hpp>
//#include <opencv2/core/utility.hpp>
#include<vector>
#include<string>
using namespace std;
std::vector<cv::String> filePathNames;
//path of folder, you can replace "*.*" by "*.jpg" or "*.png"
std::string folderPath = "C:/codes/*.*";
cv::glob(folderPath, fileNames);
// cv::string 似乎没有 find ,replace的方法
std::string stdFilePath = cvFilePath; // cv::string --->> std::string
glob 函数的原型如下
void cv::glob(cv::String pattern, std::vector<cv::String>& result, bool recursive = false)
注意 pattern 和 result 都是 cv :: String 类型。 但是 pattern 呢,即使我们传进去的参数时 std::string ,它也会自动生成一个 cv::string 的 copy。result 参数呢?因为它被当作非 const 引用,所以必须用匹配的类型。
当参数 recursive为 false 时,仅仅遍历指定文件夹内符合模式的文件,
当 recursive 为 true 时,会同时遍历指定文件夹的子文件夹。
最后,补充一个代码,来自这篇博文:
由于 glob 遍历图像名称不是按顺序进行遍历的;
在读取图像序列的时候经常要按顺序读取,如在多目标跟踪中;
这时可以 sort 进行排序;
//获取文件夹下所有图像名称,
// 图像名称按升序排列
int imageNameLists(string filePath, vector<string>& nameArr)
{
vector<cv::String> fn;
cv::glob(filePath, fn, false);
size_t count = fn.size();
if (count==0)
{
cout << "file " << filePath << " not exits"<<endl;
return -1;
}
for (int i = 0; i < count; ++i)
{
//1.获取不带路径的文件名,000001.jpg
string::size_type iPos = fn[i].find_last_of('/') + 1;
string filename = fn[i].substr(iPos, fn[i].length() - iPos);
//cout << filename << endl;
//2.获取不带后缀的文件名,000001
string name = filename.substr(0, filename.rfind("."));
//cout << name << endl;
nameArr.emplace_back(name);
}
sort(nameArr.begin(), nameArr.end(),
[](string a, string b) {return stoi(a) < stoi(b); });
return 0;
}
std::string::find() std::string::rfind()
由于对 std::string::find() std::string::rfind() 方法不熟悉,做个记录。
下面的 pos 参数是从 主串查找起点的 索引(从 0 开始),返回的是模式串在主串中的位置。
注意 (3),模式串 s 可以不被完全使用,可以用参数 n 指定只用模式串的前 n 个字符组成的子串作为模式串。
(1)size_t find (const string& str, size_t pos = 0) const; //查找对象–string类对象
(2)size_t find (const char s, size_t pos = 0) const; //查找对象–字符串
(3)size_t find (const char s, size_t pos, size_t n) const; //查找对象–字符串的前n个字符
(4)size_t find (char c, size_t pos = 0) const; //查找对象–字符
结果:找到 – 返回 第一个字符的索引
(5)string::rfind(string, pos) 是从pos开始由右往左找,返回找到的位置。
#include <iostream> // std::cout
#include <string> // std::string
int main ()
{
std::string str ("There are two needles in this haystack with needles.");
std::string str2 ("needle");
// different member versions of find in the same order as above:
std::size_t found = str.find(str2);
if (found!=std::string::npos)
std::cout << "first 'needle' found at: " << found << '\n';
// 主串是 str = "There are two needles in this haystack with needles."
// 模式串是"needles are small"的前7个字符
found=str.find("needles are small",found+1,7);
if (found!=std::string::npos)
std::cout << "second 'needle' found at: " << found << '\n';
found=str.find("haystack");
if (found!=std::string::npos)
std::cout << "'haystack' also found at: " << found << '\n';
found=str.find('.');
if (found!=std::string::npos)
std::cout << "Period found at: " << found << '\n';
// let's replace the first needle:
str.replace(str.find(str2),str2.length(),"preposition"); //replace 用法
std::cout << str << '\n';
found = str.rfind(str2);
if (found != std::string::npos)
std::cout << "From right to left, needle' found at: " << found << '\n';
return 0;
}
结果如下所示:
结果:
first 'needle' found at: 14
second 'needle' found at: 44
'haystack' also found at: 30
Period found at: 51
There are two prepositions in this haystack with needles
From right to left, needle' found at: 44
vector emplace_back() 和 push_back() 的区别
C++ STL vector 数据结构,emplace_back() 和 push_back() 的区别,就在于底层实现的机制不同。push_back() 向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素);而 emplace_back() 在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。
std::string::npos
npos是一个常数,表示size_t的最大值(Maximum value for size_t)。许多容器都提供这个东西,用来表示不存在的位置
stoi
把数字字符串转换成 int 输出。