はまってたので愚痴で書いただけです。
すべての元凶は「非同期使ってみたかった」というだけです。別スレッドありきですヽ(*^。^*)ノ
適当に無茶なことしても今のCPUならこなしてくれるはず!
(ほかの処理もバリバリ裏で動いている「はず」ですが、一番重いところの、ファイルからフレームを読み込む、サイズを変更する、画面に表示するの部分を別タスクにした例)
タスク内でまとめてやった方が高速って何?とか聞かれても、いろいろ試してくださいとしか(^◇^;
シークとかリサイズとかいろいろ。前後の処理のCPUキャッシュの乗り具合もあるだろうし、データサイズによっては全く意味がないこともあるので。これが答えだっていうのはないと思います。
TS動画再生だけなら1フレームの処理に1/30秒も余裕があるので結構なことができます。ポリゴン処理のレジスタ管理に比べたらぬるいぬるい。適当でもそれなりに動きます(笑)
まぁ、非同期でやらなければいいという話なんですが、CPU暇そうだし、読み込みを別スレッドにした時のオーバーヘッドくらい気にならんだろうという…
そのぉ、動画プレイヤーじゃないので!’`,、’`,、(ノ∀`)’`,、’`,、
OpenCVSharp使って2週間くらいのコードを少し詰めただけなんで、、、、
みんな通る道なので、、、、と、言い訳しつつ。
こんな状況でも動いていたので最適化は中断。もっと簡略化して高速化の道はあると思います。
さんぷる。Mat返すんかい!っていう突込みは置いておいてくださいw
1フレーム処理があるのと可読性のためにフレーム数を使っています。
/* 「フレーム読み込んでサイズ変更」を別スレッドにした感じ */
private async Task GetFrameAsync(int frameNum)
{
return await Task.Run(() =>
{
…
// シークのフレーム指定はミリ秒のほうが今のソースでは遅延は少なかった(スレッド内でシークしたほうが処理が速いという例)
int posMsec = (int)((1000 * frameNum) / vCapture.Fps);
vCapture.Set(CaptureProperty.PosMsec, posMsec);
// 読み込み
Mat m = new Mat();
vCapture.Read(m);
// エラー&終了処理
…
// サイズ変更する
OpenCvSharp.Size cv2_size = new OpenCvSharp.Size(previewImageWidth, previewImageHeight);
Mat thumbFrame = new Mat();
Cv2.Resize(m, thumbFrame, cv2_size);
// 加工処理やメモリ開放
…
return thumbFrame;
});
}
private async Task DrawPreviewAsync(int frameNum)
{
// フレームの“φ(._.) チェック!とかいろいろ
…
// シークのフレーム指定はミリ秒のほうが今のソースでは遅延は少なかった
//(さらに外でやって別スレッド中でやらない場合は遅いという話)
int posMsec = (int)((1000 * frameNum) / vCapture.Fps);
vCapture.Set(CaptureProperty.PosMsec, posMsec);
Mat m = await GetFrameAsync(frameNum);
if(m != null) {
PreviewImage.Source = m.ToWriteableBitmap();
}else{
…
return true;
}
※ 要点:非同期の場合ですが!
・シークはミリ秒指定にする
・スレッドの中でシークする
これだけでフレームキャプチャの処理はかなり改善されると思います。
と、未来の自分にメモを残す。
この手のヤツを集めるとかなり軽くなるんだろうなぁ・゚・(ノД`)・゚・
—課題
・capture.Read(mat);
・mat=RetrieveMat();
奥が深い。やれることはまだまだあるってことだね。
メモリ確保&使いまわし。同じサイズならもっと効率上げられそう…
ネタがないのでにゃんこの絵で癒される…
デスクトップと参考フレームが重なる瞬間!’`,、’`,、(ノ∀`)’`,、’`,、