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

相关文章

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

MySQL 表空却 ibd 文件过大的问题及解决方法

《MySQL表空却ibd文件过大的问题及解决方法》本文给大家介绍MySQL表空却ibd文件过大的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录一、问题背景:表空却 “吃满” 磁盘的怪事二、问题复现:一步步编程还原异常场景1. 准备测试源表与数据

解决Nginx启动报错Job for nginx.service failed because the control process exited with error code问题

《解决Nginx启动报错Jobfornginx.servicefailedbecausethecontrolprocessexitedwitherrorcode问题》Nginx启... 目录一、报错如下二、解决原因三、解决方式总结一、报错如下Job for nginx.service failed bec

SysMain服务可以关吗? 解决SysMain服务导致的高CPU使用率问题

《SysMain服务可以关吗?解决SysMain服务导致的高CPU使用率问题》SysMain服务是超级预读取,该服务会记录您打开应用程序的模式,并预先将它们加载到内存中以节省时间,但它可能占用大量... 在使用电脑的过程中,CPU使用率居高不下是许多用户都遇到过的问题,其中名为SysMain的服务往往是罪魁

MySQ中出现幻读问题的解决过程

《MySQ中出现幻读问题的解决过程》文章解析MySQLInnoDB通过MVCC与间隙锁机制在可重复读隔离级别下解决幻读,确保事务一致性,同时指出性能影响及乐观锁等替代方案,帮助开发者优化数据库应用... 目录一、幻读的准确定义与核心特征幻读 vs 不可重复读二、mysql隔离级别深度解析各隔离级别的实现差异

C++ vector越界问题的完整解决方案

《C++vector越界问题的完整解决方案》在C++开发中,std::vector作为最常用的动态数组容器,其便捷性与性能优势使其成为处理可变长度数据的首选,然而,数组越界访问始终是威胁程序稳定性的... 目录引言一、vector越界的底层原理与危害1.1 越界访问的本质原因1.2 越界访问的实际危害二、基

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.