opencv:avi: 非正常avi存在的问题

 

因为在录制并生成avi的时候,程序突然崩溃导致,虽然写入的图片信息,但是avi最后没有帧数的信息。

导致了win播放器可以正常的播放,但是通过opencv没办法正确读取出avi的帧数。

 

问题1: 

    //获取avi文件基本信息
	int nFps = videoCap.get(CV_CAP_PROP_FPS); //正常
	int nFrameCount = videoCap.get(CV_CAP_PROP_FRAME_COUNT); //不正常:0
	int n = videoCap.get(cv::CAP_PROP_FRAME_COUNT);//不正常:0

百度发现确实存在这种无法正常读取帧数的情况。

cvgetCaptureProperty始终为cv_cap_prop_frame_count返回0!

    int nFrameCount = videoCap.get(CV_CAP_PROP_FRAME_COUNT);
	int n = videoCap.get(cv::CAP_PROP_FRAME_COUNT);
	if (nFrameCount <= 0)
	{
		ifstream  videoFile(m_sAviPath, ios::in | ios::binary);
		// Checking the availablity of the file
		if (!videoFile) {
			std::cout << "Couldn't open the input file " << m_sAviPath << std::endl;
		}
		else
		{
			
			char tempSize[4] = {1};
			videoFile.seekg(0x30, ios::beg);
			videoFile.read(tempSize, 4);
			int frames = (unsigned char)tempSize[0] + 0x100 * (unsigned char)tempSize[1] + 0x10000 * (unsigned char)tempSize[2] + 0x1000000 * (unsigned char)tempSize[3];
		//失败了,因为二进制文件中的0x30之后的4个字节都是0x00。
			videoFile.close();
			nFrameCount = frames;
		}
	}

 

所以,想到avi一帧一帧的读取也能正常,所以想通过不断读取到cv::mat中的方法,当读取到的mat是空的时候,就表示结束了。这时候就能统计出帧数。

#include <QTime>
bool CAviTool::getAviFrameCount(std::string sAviPath, uint64_t& nFrameCount)
{
	//打开avi文件
	cv::VideoCapture videoCap(sAviPath);
	if (!videoCap.isOpened()) //检查是否打开
	{
		return false;
	}

	uint64_t nIndex = 0;//0; //23652 是会让cv 读取错误的。但是为什么呢?我只是读取有没渲染。
	QTime time;
	time.start();
	while (true)
	{
		
		videoCap.set(cv::CAP_PROP_POS_FRAMES, nIndex );

		cv::Mat mat;
		//[!] 获取单帧的方式
		//videoCap >> mat;
		videoCap.read(mat);
		if (mat.empty())
		{
			std::cout << "mat emtpy" << std::endl;
			break;
		}
		std::cout << "index  = " << nIndex <<"   use time = (ms) " << time.elapsed() << std::endl;
		time.restart();
		nIndex++;
	}
	
	nFrameCount = nIndex;
	return true;
}

最后一帧之后,会报警告信息:

 

但是这还有一个问题,就是while循环中,读取每帧的数据差不多1ms,所以当有2万帧的时候,就会出现等待20m的情况。这个太久了。

同时,不知道是有问题的avi导致的还是正常avi也有这个问题:

videoCap.set(cv::CAP_PROP_POS_FRAMES, nIndex ); nIndex 从20k开始,依旧会再读取20k后才出现cv::mat为空的情况。似乎不受nIndex 具体在影响,这样导致了 视频跳转的功能无法实现的情况了。【未找到原因和解决方法】

而这个之所以依旧可以正常获取mat的原因猜测可能是因为:videoCap >> mat; 或
        videoCap.read(mat); 每次执行后都会跳转到下一帧的位置,从而实现循环读取。

 

 

## 问题2: 如何把获取到的帧数写入到avi使得可以正常使用?

基于上面的 0x30 +  4字节的思路,想着把帧数写入到对应字节中(高位在后)。但是写入后,发现依旧没有什么改变。 和之前的没什么区别(二进制内容是改变了了,但是通过cv::** get(CV_CAP_PROP_FRAME_COUNT) 的方式还是无法正常帧数。

 

## 问题3: 其实是问题1中后面发现的videoCap.set(cv::CAP_PROP_POS_FRAMES, nIndex ); nIndex 是什么值都可以的问题。 这就导致我就算知道了avi的总帧数也没什么用了。 

这个有问题的avi导致了跳转到指定帧的功能是无效的,即无法实现跳转功能。【未找到原因和解决方法】

 

 

## 问题4: 通过avi文件大小,摄像头的像素640*360*3 (单个图片大小)来估计帧数。结果失败了,结果是avi明显较小,猜测其实在把cv::mat 写入到avi的过程中就有进行某些压缩的处理。所以这个方法完全不可行。

videoFile.seekg(0, ios::end);
uint64_t nSize = videoFile.tellg();
int nFrame = nSize / (640 * 360); 

 

 

## 其他信息
注意: cv::mat 只要 release 后 就是mat.empty() 的了。

OpenCV VideoCapture 设置和获取摄像头参数】: 但是其中没有办法写入总帧数。

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值