OpenCV - 在视频播放过程中让滑块更新其位置

时间:2011-02-19 00:15:32

标签: c++ c video opencv slider

我已经选择了“学习OpenCV”,并且一直在尝试一些代码示例/练习。在这段代码中,我想让滑块在每次视频帧更改时更新其位置,但由于某种原因它不起作用(图片冻结了以下代码):

#include "cv.h"
#include "highgui.h"

int g_slider_position = 0;
CvCapture* g_capture = NULL;

void onTrackbarSlide(int pos)
{
    cvSetCaptureProperty(g_capture, CV_CAP_PROP_POS_FRAMES, pos);
}

int main(int argc, char** argv)
{
    cvNamedWindow("The Tom 'n Jerry Show", CV_WINDOW_AUTOSIZE);
    g_capture = cvCreateFileCapture(argv[1]);
    int frames = (int) cvGetCaptureProperty(
        g_capture, 
        CV_CAP_PROP_FRAME_COUNT
        );

    if (frames != 0)
    {
        cvCreateTrackbar(
            "Position",
            "The Tom 'n Jerry Show",
            &g_slider_position,
            frames,
            onTrackbarSlide
            );
    }

    IplImage* frame;

    while (1)
    {
        frame = cvQueryFrame(g_capture);
        if (!frame) 
            break;

        cvSetTrackbarPos(
            "Position", 
            "The Tom 'n Jerry Show",
            ++g_slider_position
            );

        cvShowImage("The Tom 'n Jerry Show", frame);
        char c = cvWaitKey(33);
        if (c == 27)
            break;
    }

    cvReleaseCapture(&g_capture);
    cvDestroyWindow("The Tom 'n Jerry Show");

    return 0;
}

知道如何让滑块和视频按预期工作吗?

6 个答案:

答案 0 :(得分:6)

This is the actual working code



// PROGRAM TO ADD A UPDATING TRACKBAR TO A VIDEO

#include <cv.h>
#include <highgui.h>


int g_slider_position = 0;
CvCapture* video_capture = NULL;

void onTrackbarSlide(int current_frame)
{
    current_frame = g_slider_position;
    cvSetCaptureProperty(video_capture,CV_CAP_PROP_POS_FRAMES,current_frame);
}

int main( int argc, char** argv )
{
    cvNamedWindow( "Video", CV_WINDOW_AUTOSIZE );
    video_capture = cvCreateFileCapture( "Crowdy.avi");
    int no_of_frames = (int) cvGetCaptureProperty(video_capture,CV_CAP_PROP_FRAME_COUNT);
    if( no_of_frames!= 0 ) 
    {
        cvCreateTrackbar("Slider","Video",&g_slider_position,no_of_frames,onTrackbarSlide);
    }

    IplImage* frame;

    while(1) 
    {
        frame = cvQueryFrame( video_capture );
        if( !frame ) break;
        cvShowImage( "Video", frame );
        cvSetTrackbarPos("Slider","Video",++g_slider_position);
        char c = cvWaitKey(33);
        if( c == 27 ) break;
    }
    cvReleaseCapture( &video_capture );
    cvDestroyWindow( "Video" );

    return(0);
}

答案 1 :(得分:5)

您在代码中递增g_slider_position两次,因此它将增加超出其限制(在cvCreateTrackbar中设置为frames)。这可能会导致你的图片冻结。

要修复,请更改此

    g_slider_position++;
    cvSetTrackbarPos(
        "Position", 
        "The Tom 'n Jerry Show",
        ++g_slider_position
        );

    cvSetTrackbarPos(
        "Position", 
        "The Tom 'n Jerry Show",
        ++g_slider_position
        );

考虑编辑过的代码,我会检查OpenCV是否正确读取文件中的帧数。查看学习OpenCV的第2章,示例2.3,了解一般从AVI中检索帧数的方法(如果这是您正在使用的)。

在上面的代码中,如果帧数为0,则不会创建轨迹栏,但代码仍会进入一个尝试更新轨迹栏位置的循环(如果找到一个帧)。我会改用它:

if (frames != 0)
{
    cvCreateTrackbar(
        "Position",
        "The Tom 'n Jerry Show",
        &g_slider_position,
        frames,
        onTrackbarSlide
        );
} 
else
{
    exit(1);
}

答案 2 :(得分:3)

这对我来说似乎有点复杂。我使用cvGetCaptureProperty(g_capture, CV_CAP_PROP_POS_FRAMES)调用来检索当前帧并使用它来更新滑块。

然后使用回调函数来改变g_capture中的位置。

所以回电是:

//Call back for slider bar
void onTrackbarSlide(int pos) {
    cvSetCaptureProperty(g_capture, CV_CAP_PROP_POS_FRAMES, pos);
}

循环是:

IplImage* frame; //Frame grabbed from video
while(1) {
    frame = cvQueryFrame( g_capture );
    if (!frame ) break;
    cvShowImage( "Example2", frame );

    g_frame_count = (int) cvGetCaptureProperty(g_capture, CV_CAP_PROP_POS_FRAMES);

    cvSetTrackbarPos("Position","Example2", g_frame_count);

    char c = cvWaitKey(33);
    if ( c == 27 ) break;
}

g_变量是全局的。

答案 3 :(得分:1)

您可以尝试以下解决方案。

更改此

void onTrackbarSlide(int pos)
{
    cvSetCaptureProperty(g_capture, CV_CAP_PROP_POS_FRAMES, pos);
}

void onTrackbarSlide( int pos )
{
    if( pos > g_slider_position + 1 )
    cvSetCaptureProperty( 
        g_capture, 
        CV_CAP_PROP_POS_FRAMES, 
        pos);
}

并且也改变了这个

cvSetTrackbarPos(
            "Position", 
            "The Tom 'n Jerry Show",
            ++g_slider_position
            );

cvSetTrackbarPos(
            "Position", 
            "The Tom 'n Jerry Show",
            g_slider_position + 1
            );

答案 4 :(得分:1)

您好我有类似的代码,我做了以下内容:

void onTrackbarSlide(int pos)
{
if(pos > g_lastPosition+1 || pos < g_lastPosition)
cvSetCaptureProperty(g_capture,CV_CAP_PROP_POS_FRAMES,pos);
g_lastPosition = pos;
}

.............

while(1)
{
frame = cvQueryFrame( g_capture );
if( !frame ) break;
cvShowImage( "Example3", frame );
cvSetTrackbarPos("Position", "Example3", g_slider_position+1);
char c = cvWaitKey(33);
if( c == 27 ) break;
}

所以你可以把滑杆拉到任何方向,我希望这可以帮助

答案 5 :(得分:1)

好的,我终于解决了更新滑块的问题 如果你想移动滑块,视频也会更新 现在没有图片冻结的问题

#include "stdafx.h"

#include<cv.h>
#include<cxcore.h>
#include<highgui.h>

int g_slider_position = 0;
CvCapture* g_capture = NULL;
int count=0;              //initiate a global counter



void onTrackbarSlide( int pos )
{// if you are moving the slider for more than two frames then this loop will initiate      to
 // to update the video
    if(pos>count+2 || pos<count-2){
    cvSetCaptureProperty( 
        g_capture, 
        CV_CAP_PROP_POS_FRAMES, 
        pos);}
    count=pos;
}
int main(int argc, _TCHAR* argv[])
{
    //int count=0;
    cvNamedWindow("Example3",CV_WINDOW_AUTOSIZE);
    g_capture=cvCreateFileCapture("video.avi");
    int frames = (int) cvGetCaptureProperty(
        g_capture,
        CV_CAP_PROP_FRAME_COUNT
        );
    if(frames!= 0) {
        cvCreateTrackbar(
            "Position",
            "Example3",
            &g_slider_position,
            frames,
            onTrackbarSlide
            );
    }
    IplImage* frame;
    while (1)
    {
        count++;  // the counter will move along with the frame
        frame = cvQueryFrame( g_capture );
        if (!frame) break;
        cvShowImage ("Example3", frame);
        cvSetTrackbarPos("Position", "Example3", g_slider_position+1);
        char c = cvWaitKey(33);
        if(c==27) break;
    }

    cvReleaseCapture(&g_capture);
    cvDestroyWindow("Example3");
    return 0;
}

好了我现在所做的就是我创建了一个全局计数器,它将与框架一起更新

现在当我们将滑块与鼠标一起使用到另一个位置时,在onTrackbarSlider例程中将启动if循环并将视频设置为新位置