3

1080p ウェブカメラからファイルにビデオを録画しようとしています。ビデオでタイマーを保持しましたが、すべての試行で、ビデオ プレーヤー (私が使用したのは VLC) によって報告されたタイムスタンプがビデオの時間と同期しません。常に数秒オフです (通常、ビデオ内タイマーはプレーヤーが報告する時間よりも高速です)。

以下に示すように、あるスレッドでビデオをキャプチャし、別のスレッドで録画するように C++ プログラムをセットアップしました。CPU 使用率が ~200% であるため、これは正常に機能しています (最大出力の可能性はありますか?)。OS X 10.8 @ 1.8 GHz Intel Core i7 を搭載した Macbook Air を使用しています。

フレームレートを 15 fps に変更しようとしましたが、ビデオが途切れたり遅くなったりします。CV_CAP_PROP_FRAME_WIDTH&を低解像度に設定してみましCV_CAP_PROP_FRAME_HEIGHTたが、ビデオが遅くなります。1080p @ 30fps ではビデオが安定しているように見えますが、それでも常に想定よりも速く再生されます。waitKey(10);afterも入れてみましたrecord << frame;が、何の影響もありませんでした。

ビデオを時間内に一致させる方法に関する推奨事項はありますか?

ありがとう!アカシュ

#include "opencv/cv.h"
#include "opencv/highgui.h"
#include <boost/thread.hpp>

using namespace cv;

void captureFunc(Mat *frame, VideoCapture *capture){
    for(;;){
        // get a new frame from camera
        (*capture) >> (*frame);
    }
}

int main(int, char**)
{
    VideoCapture capture(0); // open the default camera
    if( !capture.isOpened() )  {
        printf("Camera failed to open!\n");
        return -1;
    }

    capture.set(CV_CAP_PROP_FPS,30); //set capture rate to 30fps
    Mat frame;
    capture >> frame; // get first frame for size

    // initialize recording of video
    VideoWriter record("test.avi", CV_FOURCC('D','I','V','X'), 30, frame.size(), true);
    if( !record.isOpened() ) {
        printf("VideoWriter failed to open!\n");
        return -1;
    }

    boost::thread captureThread(captureFunc, &frame, &capture); //start capture thread

    sleep(1); //just to make sure capture thread is ready

    for(;;)
    {
        // add frame to recorded video
        record << frame;
    }

    return 0;
}
4

2 に答える 2

10

少しデバッグした後、問題を解決しました。これは、VideoWriter がフレームが供給されるレートにうるさいという問題でした。

于 2013-06-28T00:14:24.410 に答える
1

読み取り機能と書き込み機能を同期する必要があります。コードは可能な限り速く読み取り、書き込みも可能な限り高速です。capture >>出力の書き込みが入力の読み取りよりも速く行われ (がカメラを待機しているため)、同じフレームがいくつか記録されるため、出力ビデオはおそらく遅く見えます。

待機または同期せずに書き込むということは、同じコンテンツを数回書き込むか (ここで起こっていると思います)、フレームを失う可能性があることを意味します。

スレッドを維持したい場合は可能ですが、新しい書き込みが発生するまで書き込みプロセスを待機させる必要があります。

同様に、フレームの損失や破損したフレームの書き込みを回避するには、frame安全に上書きできるように、書き込みが完了するまで読み取りプロセスを待機させる必要があります。

いずれにせよ、スレッドは互いに待機する必要があるため、スレッドにはほとんど意味がありません。

私はむしろこのもっと簡単な方法をお勧めします:

for (;;) {
    capture >> frame;
    process(frame);  // whatever smart you need
    record << frame;
}

並列処理が必要な場合は、はるかに複雑な同期メカニズムと、おそらくフレーム用のある種の fifo が必要になります。

于 2016-06-28T12:53:04.423 に答える