Opencv3基础学习

【opencv五】利用opencv给读入的视频添加拖动滑块

2018-12-14  本文已影响55人  yuanCruise

【opencv四】利用opencv读取显示视频中读取的视频只能正常播放,无法像我们使用播放器时能在视频中拖动进度条。本文旨在提出一个滑块功能,实现视频的进度条拖动。而之前用到过的头文件highgui.hpp除了之前用到过的读取和显示功能外,还拥有上述提到的滑块功能,使得我们能够简单的跳转到视频的某一部分。利用cv::createTrackbar()来创建滑块,并指定该滑块显示在哪个窗口中。
下述代码的功能为:在基本查看器窗口中添加一个trackbar滑块,用于在视频文件中移动。

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <fstream>

using namespace std;
using namespace cv;

int g_slider_position = 0;
int g_run = 1;
int g_dontset = 0;
VideoCapture g_cap;

void onTrackbarSlide(int pos, void *)
{
    g_cap.set(CAP_PROP_POS_FRAMES,pos);
    if (!g_dontset)
    { 
        g_run = 1;
        g_dontset = 0;
    }
}

int main()
{
    namedWindow("Example3",WINDOW_AUTOSIZE);
    g_cap.open("H:\\vs2017\\opencv_learning\\ConsoleApplication1\\video.mp4");
    int frames = (int)g_cap.get(CAP_PROP_FRAME_COUNT);
    int tmpw = (int)g_cap.get(CAP_PROP_FRAME_WIDTH);
    int tmph = (int)g_cap.get(CAP_PROP_FRAME_HEIGHT);
    cout << "Video has" << frames << "frames of dimensions(" << tmpw << "," << tmph << ")." << endl;

    createTrackbar("Position","Example3",&g_slider_position,frames,onTrackbarSlide);

    Mat frame;
    while (1)
    {
        if (g_run != 0)
        {
            g_cap >> frame;
            if (frame.empty()) break;
            int current_pos = (int)g_cap.get(CAP_PROP_POS_FRAMES);
            g_dontset = 1;

            setTrackbarPos("Position","Example3",current_pos);
            imshow("Example3",frame);

            g_run -= 1;
        }

        char c = (char)waitKey(10);
        if (c == 's') // single step
        {
            g_run = 1; cout << "Single step, run = " << g_run << endl;
        }
        if (c == 'r') // run mode
        {
            g_run = -1; cout << "Run mode, run = " << g_run << endl;
        }
        if (c == 27)
            break;
    }
    return 0;

}

代码解析:
实际上,该策略是添加一个全局变量来表示追踪视频帧位置,然后添加一个回调函数来更新该变量并重新定位视频中的读位置,用于后续的输出。一个调用创建trackbar并附加回调,然后我们就可以开始运行了。
首先看下代码中的全局变量的初始化及其作用。

int g_slider_position = 0;
int g_run = 1;
int g_dontset = 0;
VideoCapture g_cap;

为了避免混淆,当用户单击trackbar跳转到视频中的新位置时,我们将通过设置g_run = 1使视频停留在单步状态。然而,这带来了一个微妙的问题:随着视频的推进,我们希望滑动轨迹条在显示窗口中的位置根据我们在视频中的位置而前进。我们通过让主程序调用trackbar回调函数来在每次获得新的视频帧时更新滑块的位置来实现这一点。但是,我们不希望这些对trackbar回调的编程调用将我们置于单步模式。为了避免这种情况,我们引入了最后一个全局变量g_dontset,它允许我们在不触发单步模式的情况下更新轨迹条的位置。


void onTrackbarSlide(int pos, void *)
{
    g_cap.set(CAP_PROP_POS_FRAMES,pos);
    if (!g_dontset)
    { 
        g_run = 1;
        g_dontset = 0;
    }
}

该函数的功能:当用户拖动滑块的时候,利用函数callback(回调)出当前滑块的位置(视频帧数)。然后可以使得之后的显示函数 ,通过该函数回调得到的视频帧位置进行显示,最终能够实现滑块位置的拖动带动着视频的移动。

g_cap.set() 和 g_cap.get()是两个在未来会经常出现的基于视频对象的方法。这些方法主要用来配置 or 询问VideoCapture对象的各种属性。在这个例子中利用set函数将CAP_PROP_POS_FRAMES参数设置为pos,该参数的含义为以帧为单位来设置读取位置。


int frames = (int)g_cap.get(CAP_PROP_FRAME_COUNT);
int tmpw = (int)g_cap.get(CAP_PROP_FRAME_WIDTH);
int tmph = (int)g_cap.get(CAP_PROP_FRAME_HEIGHT);
cout << "Video has" << frames << "frames of dimensions(" << tmpw << "," << tmph << ")." << endl;

createTrackbar("Position","Example3",&g_slider_position,frames,onTrackbarSlide);

createTrackbar函数:用来生成视频进度条。


    if (g_run != 0)
        {
            g_cap >> frame;
            if (frame.empty()) break;
            int current_pos = (int)g_cap.get(CAP_PROP_POS_FRAMES);
            g_dontset = 1;

            setTrackbarPos("Position","Example3",current_pos);
            imshow("Example3",frame);

            g_run -= 1;
        }

在这个语句块中,程序除了对视频进行读取帧,显示外。


char c = (char)waitKey(10);
        if (c == 's') // single step
        {
            g_run = 1; cout << "Single step, run = " << g_run << endl;
        }
        if (c == 'r') // run mode
        {
            g_run = -1; cout << "Run mode, run = " << g_run << endl;
        }
        if (c == 27)
            break;

在这个语句块中,程序从用户那里寻找键盘输入。


0.给自己打个小广告

本人csdn博客地址:https://blog.csdn.net/qiu931110/
本人211硕士毕业,目前从事深度学习,机器学习计算机视觉算法行业,目前正在将我的各类学习笔记发布在我的公众号中,希望感兴趣一起学习的同学们可以关注下~~~
本人微信公众号:yuanCruise

上一篇下一篇

猜你喜欢

热点阅读