-1

私はopencvのac#ラッパーであるEmguを使って簡単なビデオプレイを書いています。

これでビデオを再生できますが、fpsが正確ではなく、通常より少し速いことがわかりました。

私のコードでは、Thread.sleep()2フレームの間でしばらく待つために使用します。コードは次のとおりです。

int fps = getFromFile(file); // which is 30
while (true) {
    var frame = CvInvoke.cvQueryFrame(capture);
    if (frame.ToInt32() == 0) break;

    Image<Bgr, byte> dest = new Image<Bgr, byte>(Convert.ToInt32(width), Convert.ToInt32(height));
    CvInvoke.cvCopy(frame, dest, IntPtr.Zero);
    box.Image = dest;

    Thread.Sleep(1000 / Convert.ToInt32(fps));
}

どこが間違っているのか、そしてそれを修正する方法は?


アップデート

boxコード内のは、Emgu.UI.ImageBoxスレッドセーフであり、他のスレッドから直接アクセスできます。box.Image = dest

4

3 に答える 3

2

フレームオブジェクトのキューを「補充」し、ある種のタイマーを使用してレンダリングする必要があります。通常、私は継続的にリサイクルされるフレームオブジェクトのプールを使用します。

簡単なビデオはありません-vlc.exe:13スレッド、realplay.exe:19スレッド、divXプレーヤー:23スレッド。

于 2012-08-09T15:24:29.247 に答える
1

私のおすすめはタイマーを使うことです

            _capture = new Capture(ofd.FileName);
            _videoTimer = new Timer();
            double fps = _capture.GetCaptureProperty(CAP_PROP.CV_CAP_PROP_FPS);
            _videoTimer.Interval =  Convert.ToInt16(1000 / fps); //the timer interval
            _videoTimer.Tick += new EventHandler(_videoTimer_Tick);
            _videoTimer.Start();

これを画像ボックスに表示します

private void _videoTimer_Tick(object sender, EventArgs e)
{
           Image<Bgr, Byte> img = _capture.QueryFrame();
            if (img == null) return; 
            box.Image = img;
}
于 2012-08-09T15:31:08.750 に答える
1

非常に小さく正確な間隔でイベントのタイミングを調整することは簡単な作業ではなく、Thread.Sleepは確かにここで必要なものではありません。

まず、Thread.Sleepは、指定された時間内にスレッドが再開することを保証するものではなく、少なくともその時間だけ中断されることを保証するだけです。

第二に、ほとんどのタイマーは、ここで必要なミリ秒レベルでは正確ではありません。これらには、System.Threading.TimerおよびSystem.Timers.Timerが含まれます。これらを使用すると、せいぜいぎくしゃくしたフレームレートが得られます。私が選択する解決策は、System.Diagostics.Stopwatchを使用して、ラグ補正を使用して独自のイベントループを作成することです。これはかなり難しいですが、OpenTKのGameWindowクラスに良い例があります。別の解決策はマルチメディアタイマーかもしれませんが、それらは.NETから直接利用できず、私はこれらを使用した経験がありません。

第3に、同じスレッドを使用して33ミリ秒ごとにレンダリングイベントを投稿したり、実際にフレームをレンダリングしたりしないでください。別のスレッドがフレームを連続してキューにレンダリングし、タイマースレッドがフロントフレームを選択するようにします。そうすれば、タイマースレッドを解放して、必要なだけ正確にすることができます。

于 2012-08-09T15:40:09.817 に答える