OpenCV - получение ползунка для обновления его позиции во время воспроизведения видео

Я взял "Learning 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;
}

Любая идея, как заставить слайдер и видео работать по назначению?

Ответ 1

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

Ответ 2

Вы увеличиваете 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);
}

Ответ 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_ являются глобальными.

Ответ 4

Вы можете попробовать решение ниже.

измените это значение

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

Ответ 5

Привет, у меня есть код simlar, и я сделал следующее:

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

Итак, вы можете захватить слайдер в любом направлении, надеюсь, это поможет

Ответ 6

OK Я, наконец, решил эту проблему обновления ползунка а также, если вы хотите переместить слайдер, видео будет обновляться теперь нет проблемы с замораживанием изображения.

#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 теперь то, что я сделал, это то, что я создал глобальный счетчик, который будет обновляться вместе с кадрами

теперь, когда мы используем слайдер с мышью в другую позицию, а затем в режиме onTrackbarSlider цикл if будет инициирован, и он установит видео в новую позицию