OpenCV 2.3.1 中关于cvCaptureProperty()定位不准的问题

2023-11-30 05:32

本文主要是介绍OpenCV 2.3.1 中关于cvCaptureProperty()定位不准的问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

      转自http://hi.baidu.com/windroc/blog/item/f6a565638d5eeb7c0d33fa27.html      

      HIGHGUI ERROR: AVI: could not seek to position      

      问题说明:

      OpenCV 2.X 版本中,调用cvCaptureProperty()定位视频到指定帧,采用下面两种方法都会出现定位不准的问题。

 

cvSetCaptureProperty( capture, CV_CAP_PROP_POS_AVI_RATIO, t)  

cvSetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES, t);   

都会显示诸如此类的错误警告信息: 

HIGHGUI ERROR: AVI: could not seek to position  2.701

其中黄色数字就是OpenCV函数中对应的帧数,不知道因为什么原因,变成非整数,与之前程序中指定的帧数不一致,导致无法定位到准确的位置。

之前用OpenCV 2.2版本,一样出现相同的问题。而使用OpenCV 1.1版本,就可以正常定位。

更详细的问题说明:

很多人都遇到这个问题,更详细的实验可以参见下面文章:

设定cvSetCaptureProperty后取帧不准的问题

作者实验中使用的测试代码如下:
#include "highgui.h"  
#include <iostream>
using namespace std;
int main( int argc, char** argv )
{
cvNamedWindow( "Example2", CV_WINDOW_AUTOSIZE );
CvCapture* capture = cvCreateFileCapture( "d://11.avi" );
IplImage* frame;

int pos=0;
int pos1=0;
while(1)
{
cvSetCaptureProperty(capture,CV_CAP_PROP_POS_FRAMES,pos);
cout<<pos;
frame = cvQueryFrame(capture);

pos1=cvGetCaptureProperty(capture,CV_CAP_PROP_POS_FRAMES);
cout<<"\t"<<pos1<<endl;

if( !frame ) break;
cvShowImage( "Example2", frame );
char c = cvWaitKey(33);
if( c == 27 ) break;

pos++;
}
cvReleaseCapture( &capture );
cvDestroyWindow( "Example2" );

}

 

作者发现,在OpenCV 2.X版本中,随着pos值递增,pos1值并不与pos1相等,而是有不规则的跳动,造成无法准确定位视频帧。


原因与改进方法:

具体原因和改进方法,参考下面的讨论

OpenCV 中文论坛 查看主题 - 新手问一个设定cvSetCaptureProperty后取帧不准的问题

及文章:

opencv中cvSetCaptureProperty定位不准的原因及解决

作者指出:

原因在于opencv2.0以后,采用ffmpeg采集视频,而在opencv1.0采用vfw采集视频(具体的概念暂时还不清楚,有时间继续补上)。而opencv在定位时候,调用的ffmpeg的av_seek_frame()函数,此函数原型为:

int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags);  

其中,最后一个参数有

AVSEEK_FLAG_BACKWARD = 1; ///< seek backward
AVSEEK_FLAG_BYTE = 2; ///< seeking based on position in bytes
AVSEEK_FLAG_ANY = 4; ///< seek to any frame, even non key-frames

ffmpeg默认的是选取关键帧(这个概念需要具体定义)。opencv里面这个函数的参数flag是0,

int ret = av_seek_frame(ic, video_stream, timestamp, 0) ;  

也就是按照默认的读取关键帧。因此,视频跳跃就出现了。

解决这个问题需要将0改为 AVSEEK_FLAG_ANY ,即:

int ret = av_seek_frame(ic, video_stream, timestamp, AVSEEK_FLAG_ANY );

之后重新编译opencv库,就可以了。


我在OpenCV 2.3.1中的处理方法:

OpenCV 2.3.1中的与cvCaptureProperty()和FFMPEG相关的文件是:opencv2.3.1解压目录\modules\highgui\src\cap_ffmpeg_impl.hpp

在函数 bool CvCapture_FFMPEG::setProperty( int property_id, double value ) 中

相关的原始代码如下:

int flags = AVSEEK_FLAG_FRAME;  
if (timestamp < ic->streams[video_stream]->cur_dts)
flags |= AVSEEK_FLAG_BACKWARD;
int ret = av_seek_frame(ic, video_stream, timestamp, flags);
if (ret < 0)
{
fprintf(stderr, "HIGHGUI ERROR: AVI: could not seek to position %0.3f\n",
(double)timestamp / AV_TIME_BASE);
return false;
}

问题就在于flags的值为 AVSEEK_FLAG_FRAME,而不是AVSEEK_FLAG_ANY

仅修改第一行,还是不能达到效果。

与OpenCV 2.0的代码进行比较,发现OpenCV 2.0的代码更少,在2.0版本基础上进行修改:

int ret = av_seek_frame(ic, video_stream, timestamp, AVSEEK_FLAG_ANY);  
if (ret < 0) 

fprintf(stderr, "HIGHGUI ERROR: AVI: could not seek to position %0.3f\n", 
(double)timestamp / AV_TIME_BASE); 
return false; 

这样就可以正确定位了,但还不清楚这样修改对2.3整体代码有什么影响,有待更进一步研究。

这篇关于OpenCV 2.3.1 中关于cvCaptureProperty()定位不准的问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/435816

相关文章

Python中OpenCV与Matplotlib的图像操作入门指南

《Python中OpenCV与Matplotlib的图像操作入门指南》:本文主要介绍Python中OpenCV与Matplotlib的图像操作指南,本文通过实例代码给大家介绍的非常详细,对大家的学... 目录一、环境准备二、图像的基本操作1. 图像读取、显示与保存 使用OpenCV操作2. 像素级操作3.

C/C++中OpenCV 矩阵运算的实现

《C/C++中OpenCV矩阵运算的实现》本文主要介绍了C/C++中OpenCV矩阵运算的实现,包括基本算术运算(标量与矩阵)、矩阵乘法、转置、逆矩阵、行列式、迹、范数等操作,感兴趣的可以了解一下... 目录矩阵的创建与初始化创建矩阵访问矩阵元素基本的算术运算 ➕➖✖️➗矩阵与标量运算矩阵与矩阵运算 (逐元

C/C++的OpenCV 进行图像梯度提取的几种实现

《C/C++的OpenCV进行图像梯度提取的几种实现》本文主要介绍了C/C++的OpenCV进行图像梯度提取的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录预www.chinasem.cn备知识1. 图像加载与预处理2. Sobel 算子计算 X 和 Y

C/C++和OpenCV实现调用摄像头

《C/C++和OpenCV实现调用摄像头》本文主要介绍了C/C++和OpenCV实现调用摄像头,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录准备工作1. 打开摄像头2. 读取视频帧3. 显示视频帧4. 释放资源5. 获取和设置摄像头属性

c/c++的opencv图像金字塔缩放实现

《c/c++的opencv图像金字塔缩放实现》本文主要介绍了c/c++的opencv图像金字塔缩放实现,通过对原始图像进行连续的下采样或上采样操作,生成一系列不同分辨率的图像,具有一定的参考价值,感兴... 目录图像金字塔简介图像下采样 (cv::pyrDown)图像上采样 (cv::pyrUp)C++ O

c/c++的opencv实现图片膨胀

《c/c++的opencv实现图片膨胀》图像膨胀是形态学操作,通过结构元素扩张亮区填充孔洞、连接断开部分、加粗物体,OpenCV的cv::dilate函数实现该操作,本文就来介绍一下opencv图片... 目录什么是图像膨胀?结构元素 (KerChina编程nel)OpenCV 中的 cv::dilate() 函

MySQL启动报错:InnoDB表空间丢失问题及解决方法

《MySQL启动报错:InnoDB表空间丢失问题及解决方法》在启动MySQL时,遇到了InnoDB:Tablespace5975wasnotfound,该错误表明MySQL在启动过程中无法找到指定的s... 目录mysql 启动报错:InnoDB 表空间丢失问题及解决方法错误分析解决方案1. 启用 inno

Java使用MethodHandle来替代反射,提高性能问题

《Java使用MethodHandle来替代反射,提高性能问题》:本文主要介绍Java使用MethodHandle来替代反射,提高性能问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录一、认识MethodHandle1、简介2、使用方式3、与反射的区别二、示例1、基本使用2、(重要)

电脑蓝牙连不上怎么办? 5 招教你轻松修复Mac蓝牙连接问题的技巧

《电脑蓝牙连不上怎么办?5招教你轻松修复Mac蓝牙连接问题的技巧》蓝牙连接问题是一些Mac用户经常遇到的常见问题之一,在本文章中,我们将提供一些有用的提示和技巧,帮助您解决可能出现的蓝牙连接问... 蓝牙作为一种流行的无线技术,已经成为我们连接各种设备的重要工具。在 MAC 上,你可以根据自己的需求,轻松地

Java 中的跨域问题解决方法

《Java中的跨域问题解决方法》跨域问题本质上是浏览器的一种安全机制,与Java本身无关,但Java后端开发者需要理解其来源以便正确解决,下面给大家介绍Java中的跨域问题解决方法,感兴趣的朋友一起... 目录1、Java 中跨域问题的来源1.1. 浏览器同源策略(Same-Origin Policy)1.