Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV - getting the slider to update its position during video playback

I've picked up 'Learning OpenCV' and have been trying some of the code examples/exercises. In this code snippet, I want to get the slider to update its position with each video frame change, but for some reason it won't work (the picture freezes with the following code):

#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;
}

Any idea how to get the slider and video to work as intended?

like image 484
Kristian D'Amato Avatar asked Feb 19 '11 00:02

Kristian D'Amato


6 Answers

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);
}
like image 129
sameer Avatar answered Oct 14 '22 14:10

sameer


You are incrementing g_slider_position twice in the code, so it will increment beyond its limit (set in cvCreateTrackbar as frames). This is likely causing your picture to freeze.

To fix, change this

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

to

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

Accounting for the edited code, I would check that OpenCV is properly reading the number of frames from your file. Look at Learning OpenCV's Chapter 2, example 2.3 for a method of generically retrieving the number of frames from your AVI (if that is what you are using).

In your code above, if the number of frames is 0, the trackbar is not created but the code still enters a loop that attempts to update the trackbar position (if it finds a frame). I would use this instead:

if (frames != 0)
{
    cvCreateTrackbar(
        "Position",
        "The Tom 'n Jerry Show",
        &g_slider_position,
        frames,
        onTrackbarSlide
        );
} 
else
{
    exit(1);
}
like image 24
Seth Avatar answered Oct 14 '22 12:10

Seth


This seems a bit complicated to me. I used the cvGetCaptureProperty(g_capture, CV_CAP_PROP_POS_FRAMES) call to retrieve the current frame and used this to update the slider.

The callback function is then used just to change the position within g_capture.

So the call back is:

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

And the loop is:

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;
}

Where the g_ variables are global.

like image 20
James Avatar answered Oct 14 '22 14:10

James


You can try the solution below.

change this

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

to

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

and also change this

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

to

cvSetTrackbarPos(
            "Position", 
            "The Tom 'n Jerry Show",
            g_slider_position + 1
            );
like image 45
Duong Truong Avatar answered Oct 14 '22 12:10

Duong Truong


Hi I have simlar code and I did the following:

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;
}

So you can grab the slide bar to any direction , I hope this can help

like image 23
metalknite Avatar answered Oct 14 '22 13:10

metalknite


OK I finally solved this problem of updating the slider and also if you want to move the slider the video will update there is no problem of picture freezing now

#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;
}

ok now what i have done is that i have created a global counter which will be updated alongside with the frames

now when we use the slider with the mouse to a different position then in onTrackbarSlider routine the if loop will be initiated and it will set the video to the new position

like image 38
Saad Avatar answered Oct 14 '22 12:10

Saad