从/在一个目录中加载/保存多个图像 - opencv c++
Posted
技术标签:
【中文标题】从/在一个目录中加载/保存多个图像 - opencv c++【英文标题】:load/save multiple images from/in a directory - opencv c++ 【发布时间】:2018-07-30 11:05:06 【问题描述】:我想从一个目录加载很多图像(虽然不是顺序名称)。编辑它们,然后尽可能将它们保存在具有原始名称的不同目录中。 我这样加载它们:
glob("/photos/field_new/*.jpg", fn, false);
size_t count = fn.size(); //number of jpg files in images folder
for (size_t i=0; i<count; i++)
images.push_back(imread(fn[i]));
有什么想法可以将它们保存在目录 /photos/results/ 中吗? 如果可能的话,用他们原来的名字?
【问题讨论】:
如果可以使用,我会推荐filesytem library,特别是path class。唯一的问题是它是 c++17 我会使用 dirent.h 文件和函数 使用了增强。工作正常! 【参考方案1】:如果你有 C++17,这会很容易,因为标准中有文件系统库(std::filesystem)。否则,我会建议您获得非常相似的 boost::filesystem(您应该很好地将所有 std::filesystem 替换为 boost::filesystem)。
要从某个文件夹加载所有图像,有 2 个辅助函数:
#include <filesystem> //for boost change this to #include <boost/filesystem> and all std:: to boost::
#include <opencv2/opencv.hpp>
bool isSupportedFileType(const std::filesystem::path& pathToFile,
const std::vector<std::string>& extensions)
auto extension = pathToFile.extension().string();
std::transform(extension.begin(), extension.end(), extension.begin(), [](char c)
return static_cast<char>(std::tolower(c));
);
return std::find(extensions.begin(), extensions.end(), extension) != extensions.end();
std::tuple<std::vector<cv::Mat>, std::vector<std::filesystem::path>> loadImages(const std::filesystem::path& path,
const std::vector<std::string>& extensions)
std::vector<cv::Mat> images;
std::vector<std::filesystem::path> names;
for (const auto& dirIt : filesystem::DirectoryIterator(path))
if (std::filesystem::is_regular_file(dirIt.path()) && isSupportedFileType(dirIt.path(), extensions))
auto mask = cv::imread(dirIt.path().string(), cv::IMREAD_UNCHANGED);
if (mask.data != nullptr) //there can be problem and image is not loaded
images.emplace_back(std::move(mask));
names.emplace_back(dirIt.path().stem());
return images, names;
你可以这样使用它(假设 C++17):
auto [images, names] = loadImages("/photos/field_new/", ".jpg", ".jpeg");
或 (C++11)
auto tupleImageName = loadImages("/photos/field_new/", ".jpg", ".jpeg");
auto images = std::get<0>(tupleImageName);
auto names = std::get<1>(tupleImageName);
要保存你可以使用这个功能:
void saveImages(const std::filesystem::path& path,
const std::vector<cv::Mat>& images,
const std::vector<std::filesystem::path>& names)
for(auto i = 0u; i < images.size(); ++i)
cv::imwrite((path / names[i]).string(), images[i]);
像这样:
saveImages("pathToResults",images,names);
在此保存功能中,如果图像数量与名称相同,最好执行一些验证,否则可能会出现超出矢量边界的问题。
【讨论】:
我认为我正在使用 c++11,所以我将使用 boost::filesystem。我现在将尝试代码。但要正确:我将这两个函数粘贴到我的程序中,然后调用类似“auto [images, names] = loadImages("/photos/field_new/", ".jpg", ".jpeg") 之类的函数;"在我的主要?然后我有两个数组,一个带有图像,一个带有名称? 如果你使用的是 c++11 会有区别。我会更新帖子。但是,是的,如果您在 main 中调用此函数,它将加载所有内容。 我收到此错误:致命错误:文件系统:没有此类文件或目录编译终止。 --- 当我删除我定义文件系统的行时,我得到这个错误:'boost'没有命名类型 bool isSupportedFileType(const boost::filesystem::path& pathToFile, 因为#include以上是关于从/在一个目录中加载/保存多个图像 - opencv c++的主要内容,如果未能解决你的问题,请参考以下文章
当我在我的 android 应用程序中从图库中加载图像时,为啥位图返回较小的图像?