使用open cv

时间:2016-09-06 00:38:11

标签: c++ multithreading opencv boost

我需要使用OpenCV制作小型视频播放器,它必须支持以下功能。关键' p'在键盘上 - 暂停/取消暂停,' q' - 退出,左右箭头键 - 在暂停时直接和反向播放视频。所以问题是当我尝试显示高质量的视频时,我按住箭头键几秒钟它不会运行,但冻结然后在我释放键后跳转到当前帧。我试图通过在this_thread::sleep之后添加cv::imshow()来解决此问题,以便有时间绘制,但它根本没有帮助。所以这是代码。另外,我有一些理由使用boost代替C ++ 11,所以没关系。

main.cpp
#include "VideoPlayer.hpp"

#include <iostream>

int main(int argc, char *argv[])
{
    if (argc < 2) {
        std::cerr << "Video file full name required as argument." << std::endl;
    }

    VideoPlayer vp(argv[1]);
    if (!vp.play())
        return 1;

    return 0;
}

VideoPlayer.hpp
#pragma once

#include <opencv/cxcore.hpp>
#include <opencv/highgui.h>

#include <string>

class VideoPlayer
{
public:
    VideoPlayer(const std::string &video, const std::string &windowName = "Output window",
            unsigned int delay = 30);
    bool play();

private:
    cv::VideoCapture videoCapture_;
    std::string windowName_;
    unsigned int delay_;

private:
   bool processKey(int key);
   void setFrame(int frameNum);
};

VideoPlayer.cpp
#include "VideoPlayer.hpp"

#include <iostream>

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread/thread.hpp>

VideoPlayer::VideoPlayer(const std::string &video, const std::string &windowName,
                     unsigned int delay)
    : videoCapture_(video)
    , windowName_(windowName)
    , delay_(delay)
{}

bool VideoPlayer::play()
{
    if (!videoCapture_.isOpened()) {
        std::cerr << "Unable to open video." << std::endl;
        return false;
    }
    cv::namedWindow(windowName_);
    for (;;) {
        cv::Mat frame;
        videoCapture_ >> frame;
        cv::imshow(windowName_, frame);
        int key = cv::waitKey(delay_);
        if (processKey(key))
            break;
    }
    return true;
}

bool VideoPlayer::processKey(int key)
{
    if (key == 'p') {
        for (;;) {
            int pausedKey = cv::waitKey(0);
            if (pausedKey == 'p') {
                break;
            } else if (pausedKey == 'q') {
                return true;
            } else if (pausedKey == 65363) {
                int frameNum = videoCapture_.get(CV_CAP_PROP_POS_FRAMES);
                setFrame(frameNum);
            } else if (pausedKey == 65361) {
                int frameNum = videoCapture_.get(CV_CAP_PROP_POS_FRAMES);
                setFrame(frameNum - 2);
            }
        }
    } else if (key == 'q') {
        return true;
    }
    return false;
}

void VideoPlayer::setFrame(int frameNum)
{
    if (frameNum > 0 && frameNum < videoCapture_.get(CV_CAP_PROP_FRAME_COUNT)) {
        std::cerr << frameNum << std::endl;
        videoCapture_.set(CV_CAP_PROP_POS_FRAMES, frameNum);
        cv::Mat frame;
        videoCapture_ >> frame;
        cv::imshow(windowName_, frame);
        boost::this_thread::sleep(boost::posix_time::milliseconds(10));
    }
}

我还使用带有锁的std::queue创建了一个带有缓冲区的多线程实现,但它并没有解决问题。我尝试使用boost::lockfree::queue,但由于一些奇怪的行为,我无法完成它。如果有必要,我稍后会分享这段代码。 所以,如果有人知道一些好的做法,如何避免这个问题,请帮助我。

编辑:

boost::this_thread::sleep(boost::posix_time::milliseconds(10));替换cv::waitKey(0)是不好的,因为这会让我在箭头键上按两次短按来更改一帧,但它没有帮助,因为按住键会非常快地跳过它。所以下面的代码有所帮助,但它太奇怪了,每个视频都需要选择times

void VideoPlayer::setFrame(int frameNum)
{
    if (frameNum > 0 && frameNum < videoCapture_.get(CV_CAP_PROP_FRAME_COUNT)) {
        std::cerr << frameNum << std::endl;
        videoCapture_.set(CV_CAP_PROP_POS_FRAMES, frameNum);
        cv::Mat frame;
        videoCapture_ >> frame;
        cv::imshow(windowName_, frame);
        int times = 7;
        for (int i = 0; i < times; i++)
            cv::waitKey(10);
    }
}

另外,我无法使用Qt或其他东西,只有C ++ 03使用boost和OpenCV。 我想我需要一些技巧让cv::waitKey(time)等待time是否按下任何键。

0 个答案:

没有答案