OpenCV_读取文件夹下的图片生成视频文件

本文介绍如何用OpenCV从指定文件夹读取所有图片并生成avi视频文件。若生成的视频文件大小为0KB,可能因缺少Xvid编解码器。解决方法是下载并安装Xvid编解码器。


下面这段代码实现了:使用OpenCV读取指定文件夹下的所有图片,然后生成avi视频文件。




//  读取文件夹下的图片生成视频文件
//  Author:www.icvpr.com
//  Blog:  http://blog.youkuaiyun.com/icvpr  

#include <iostream>
#include <string>
#include <io.h>

#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main(int argc, char** argv)
{
	// 图片集
	string fileFolderPath = "..\\images";
	string fileExtension = "jpg";
	string fileFolder = fileFolderPath + "\\*." + fileExtension;

	// 输出视频
	string outputVideoName = "output.avi";
	
	// openCV video writer
	VideoWriter writer;
	
	int codec = 0;
	int frameRate = 25;
	Size frameSize;


	// 遍历文件夹
	char fileName[1000];

	struct _finddata_t fileInfo;    // 文件信息结构体

	// 1. 第一次查找
	long findResult = _findfirst(fileFolder.c_str(), &fileInfo);          
	if (findResult == -1)
	{
		_findclose(findResult); 
<think>好的,我现在需要帮助用户解决如何使用C++和OpenCV批量读取文件夹中的所有图片的问题。用户已经提供了一些之前的回答和引用内容,我需要综合这些信息来给出一个全面且准确的解决方案。 首先,用户之前的问题是关于批量保存图片按数字序号命名,而现在的问题是批量读取图片。之前的回答中已经提到了使用cv::glob函数来获取文件路径列表,这可能在这里同样适用。引用中的几个例子也展示了不同的方法,比如使用cv::glob或者cv::utils::fs::glob,还有一些类封装的方法。 我需要确认OpenCV版本的问题,因为引用中提到在OpenCV3.X之后,contrib模块需要自己编译,但cv::glob是自带的函数。因此,在回答时需要说明不同版本的方法,确保用户知道如何根据他们的版本来选择正确的函数。 用户可能的需求不仅仅是读取图片,还可能包括如何处理读取过程中的错误,比如文件不存在或无法读取的情况。同时,用户可能希望代码结构清晰,比如使用类来封装读取功能,如引用中的Ve类。 另外,用户可能关心跨平台的问题,比如路径分隔符的处理,是否需要使用正斜杠或反斜杠,这在之前的回答中也提到了统一使用正斜杠以避免问题。此外,是否需要递归遍历子文件夹,引用中的glob函数有一个参数可以控制是否递归,需要说明这一点。 还有,用户可能想知道如何显示图片或者进行进一步的处理,但根据当前问题,重点应放在读取上。不过,引用中的示例代码有的包含显示图片的部分,可能需要提及,但保持回答的专注性。 需要检查引用中的代码是否存在潜在问题,例如在读取图片时是否检查了图像是否为空,避免程序崩溃。比如引用1中的代码在读取后直接emplace_back,但没有检查是否读取,这可能导致问题,所以应该在回答中加入错误处理的建议。 另外,用户可能对性能有要求,比如一次性读取所有图片到内存中是否可行,如果图片很多,可能会占用大量内存,但根据问题描述,用户可能只是需要基本的读取方法,因此可以建议在循环中逐个处理,而不是全部加载到内存。 总结步骤应该是:获取文件路径列表,遍历每个路径,读取图片,检查是否有效,然后处理或存储。需要提供两种方法,一种是使用cv::glob,另一种是使用cv::utils::fs::glob(如果有的话),说明版本差异。 最后,确保代码示例正确,包括必要的头文件和命名空间,路径处理的注意事项,以及错误检查的部分,比如检查文件列表是否为空,处理无法读取图片文件。</think>#### 基于OpenCV的C++批量读取图片方法 以下是两种常用方法实现文件夹图片批量读取,涵盖不同OpenCV版本和代码封装方式: --- ### 方法一:使用`cv::glob`(OpenCV 3.0+通用) **核心步骤:** 1. **路径配置**:使用通配符定义文件匹配模式(如`*.jpg`) 2. **路径获取**:`cv::glob`函数扫描目录生成路径列表 3. **循环读取**:遍历路径列表加载图像数据 ```cpp #include <opencv2/opencv.hpp> #include <vector> #include <iostream> int main() { // 配置输入路径(注意斜杠方向) std::string inputPattern = "D:/dataset/images/*.png"; // 获取所有匹配文件路径 std::vector<cv::String> imagePaths; cv::glob(inputPattern, imagePaths); // 错误检查 if(imagePaths.empty()) { std::cerr << "错误:未找到匹配图片" << std::endl; return -1; } // 批量读取 std::vector<cv::Mat> images; for(const auto& path : imagePaths) { cv::Mat img = cv::imread(path, cv::IMREAD_COLOR); // 以彩色模式读取 if(!img.empty()) { images.push_back(img); std::cout << "读取: " << path << std::endl; } else { std::cerr << "读取失败: " << path << std::endl; } } return 0; } ``` --- ### 方法二:使用`cv::utils::fs::glob`(OpenCV 4.5+推荐) **版本优势**: - 更严格的路径检查 - 支持递归遍历子目录(通过`recursive=true`参数) - 明确的文件存在性验证 ```cpp #include <opencv2/opencv.hpp> #include <opencv2/core/utils/filesystem.hpp> #include <vector> #include <iostream> int main() { std::string imgDir = "../input_images"; // 检查目录存在性 if(!cv::utils::fs::exists(imgDir)) { std::cerr << "错误:目录不存在" << std::endl; return -1; } // 获取所有JPG文件路径 std::vector<cv::String> imgPaths; cv::utils::fs::glob(imgDir, "*.jpg", imgPaths); // 批量读取(带异常处理) try { std::vector<cv::Mat> imageData; for(const auto& path : imgPaths) { cv::Mat img = cv::imread(path); if(img.empty()) throw std::runtime_error("图像加载失败: " + path); imageData.push_back(img.clone()); // 深拷贝避免内存冲突 } std::cout << "读取" << imageData.size() << "张图片" << std::endl; } catch(const std::exception& e) { std::cerr << "异常: " << e.what() << std::endl; } return 0; } ``` --- ### 关键差异对比表 | 特性 | `cv::glob` | `cv::utils::fs::glob` | |--------------------|-----------------------------|-------------------------------| | OpenCV版本要求 | ≥3.0 | ≥4.5(需编译contrib模块) | | 路径检查 | 无自动检查 | 支持`exists()`目录存在性验证 | | 递归遍历 | 需设置`bool recursive`参数 | 同左 | | 通配符灵活性 | 支持`*`和`?` | 同左 | | 跨平台兼容性 | 高 | 高 | --- ### 最佳实践建议 1. **路径规范**:统一使用正斜杠`/`,避免Windows反斜杠转义问题 ```cpp std::string path = "C:/dataset/2023/images/*.jpg"; // 正确 // std::string path = "C:\dataset\images"; // 错误(转义符问题) ``` 2. **内存优化**:大尺寸图像建议逐张处理而非全加载 ```cpp for(const auto& path : imagePaths) { cv::Mat img = cv::imread(path); processImage(img); // 立即处理单张 } ``` 3. **异常处理**:通过`try-catch`捕获读取异常 ```cpp try { cv::Mat img = cv::imread("invalid_path.jpg"); if(img.empty()) throw std::runtime_error("文件损坏或路径错误"); } catch(...) { // 处理异常 } ``` 4. **扩展名过滤**:多格式支持时使用通配符组合 ```cpp cv::glob("input/*.{jpg,png,bmp}", imagePaths); // 读取JPG/PNG/BMP ``` --- ### 常见问题解决 **Q1: 为什么`cv::glob`返回空列表?** - 检查路径权限(确保程序有访问权限) - 验证通配符是否正确(如`*.jpg`匹配扩展名严格区分大小) - 使用绝对路径替代相对路径 **Q2: 如何实现子目录递归遍历?** 设置`recursive`参数为`true`: ```cpp cv::glob("dataset/**/*.png", imagePaths, true); // **表示递归所有子目录 ``` **Q3: 读取后图像数据为何异常?** - 检查`cv::imread`的第二个参数(如`cv::IMREAD_GRAYSCALE`指定灰度模式) - 验证文件是否损坏(用图片查看器手动打开测试) ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值