スキーターンモニターでスキーの滑走データと自撮り360度動画をたくさん撮ってきたのはいいのですが、これらを同期させて、欲しいフレーム位置でのモーションデータと動画を眺めないとモーションデータが正しいのかわかりません。そこで、4日かけて、MP4ファイルとVB.NETのリアルタイムグラフの同期方法を検討しました。
完成した動画処理プログラムは、YOUTUBEでしか動作確認できませんのでご覧ください。
モーションデータとフレーム画像の時間精度は、±15msec程度まで同期していると思います。
3月末までに海外メーカーのHPで本システムを紹介するので英語版で作成してます。
※2021年夏に、グラフをBitmap化して、任意に切り取って表示する描画方法を学習しました。
グラフィックが遅いPCでも高速にグラフが動きます。リアルタイムグラフもできます。
グラフをBitmap化することで、拡大、縮小、カーソル更新が簡単に高速にできるようになります。MP4映像と対比させるグラフィックに自由度が増えて、アピール効果が大きくなります
●スキーの自動追尾グラフの解説記事は、3本あります。
【STA】RTKデータ解析用グラフィック機能開発ーその1ー<自動追尾機能便利>
【STA】RTKデータ解析用グラフィック機能開発ーその2ー<ソースBITMAP表示基礎>
【STA】RTKデータ解析用グラフィック機能開発ーその3ー<自動追尾機能の中身>
●リアルタイムグラフの bitmap化で便利なグラフツールができました。
【VB.NET】リアルタイムグラフBitmap化<その2カーソルと拡大縮小>
①WindowsMediaPlayer コントロールでは、コマ送りプログラムは、無理
参考にさせていただいたサイト様感謝です。
http://www43.tok2.com/home/zeromethod/VB-axMediaPlayer.html
フォームアプリのツールボックスに参照追加すればパーツとして
WindowsMediaPlayerがVB.NETで見ることができます。
メリット:非常に簡単に動画再生できる点
デメリット:秒単位でしか、停止位置指定ができない
=>手動のコマ送りはできるが、プログラムからフレーム数を指定して
停止ができない。
②漫画式の検討
MP4のフレームを静止画として、数千枚作って、それをVBフォームに表示しながら、漫画式にパラパラとコマ送りする方式を作ってみました。
メリット:フレーム単位で正確な時刻制御ができて、モーションデータと同期可能
デメリット:SSD容量を食う、実速度再生はできない
=>30fpsで1分のMP4で、約1800ファイルの静止画ができて、1640×720で
も約2GB程度ディスク容量と食います。
●漫画式を採用
モーションデータとコマ送りの時間精度が最重要なので、ディスク容量を
犠牲にしてでも、漫画式でプログラムを組んでみました。
①VBで静止画を表示する方法
おなじみDOBONネット様に何個かサンプルプログラムがありました。
https://dobon.net/vb/dotnet/graphics/zoominout.html
このサンプルだとマウスクリックで画像の縮小率を変えたり、位置を変えたりできますが、私の場合は固定位置、固定縮小率なのでマウス関係を消して
シンプルな静止画読み込みSUBにしました。
■動作の仕組み
imageデータをファイルから読み込んで、PictureBox2.Invalidate()すると
イベントハンドラSUBが描画実行するという仕組みです。
koma(コマ番号)というSUBに改造しました。ファイル名連番を書き換えながら読み込みます。ここではpngファイルを読み込んでます。pngのほうが色がjpgよりきれいなので、pngを採用してます。
‘=========================KomaOkuri SUB======================================= Private Sub koma(ByVal n As Integer) Dim images(2000) Dim fstr As String = “C:\SkiPic\210301_1323_DT\Produce_” ’01.jpg” Dim fnstr As String fnstr = (n).ToString(“D4”) + “.png” fstr = fstr + fnstr Label31.Text = fstr images(i) = Image.FromFile(fstr) ‘images(1) = Image.FromFile(“C:\SkiPic\Produce_401.jpg”) currentImage = images(i) ‘ Panel1.Invalidate() ‘倍率変更後の画像のサイズと位置を計算する drawRectangle.Width = 640 ‘固定値に変更、CInt(Math.Round(currentImage.Width * zoomRatio)) drawRectangle.Height = 360 ‘固定値に変更、CInt(Math.Round(currentImage.Height * zoomRatio)) drawRectangle.X = 0 ‘固定値に変更、CInt(Math.Round(pb.Width / 2.0 – imgPoint.X * zoomRatio)) drawRectangle.Y = 0 ‘固定値に変更、CInt(Math.Round(pb.Height / 2.0 – imgPoint.Y * zoomRatio)) ‘ Label33.Text = “dR.Width=” + CStr(drawRectangle.Width) + “dR.Heght=” + CStr(drawRectangle.Height) + “dR.X=” + CStr(drawRectangle.X) + “dR.Y=” + CStr(drawRectangle.Y) ‘画像を表示する PictureBox2.Invalidate() Label33.Text = “komaN=” + CStr(n) + “koma0=” + CStr(koma0) + “komaN-koma0=” + CStr(n – koma0)End Sub |
これを描画するSUBは、これだけで済みます。
Private Sub PictureBox2_Paint(sender As Object, e As PaintEventArgs) _ Handles PictureBox2.Paint If Not (currentImage Is Nothing) Then ‘画像を指定された位置、サイズで描画する e.Graphics.DrawImage(currentImage, drawRectangle) End If End Sub |
■MP4からフレーム静止画を大量に作成する方法
PowerDirectorを使ってますが、大概の動画編集ソフトに静止画に一括変換する機能がついてます。
※無料の動画編集ソフトのAVIutlでもあります。https://aviutl-douga.com/renban/
PowerDirectorで連番静止画を出力する方法は
https://help.cyberlink.com/stat/help/powerdirector/18/jpn/19_02_02_image_sequence.html
元MP4をタイムラインで範囲指定して出力します。出力の方法で
「イメージシーケンス」image seaquencreを指定すれば静止画を指定時間分大量に連番をつけて指定フォルダーの作成してくれます。
●イメージシーケンスのはまりどころ
fps指定はできるのですが、正確な時間間隔で、静止画を切り取ってくれませんでした。29.976fpsなら33.3667msecなのですが、実際は、41.42msecでした。これに気づくには、静止画の総枚数をチェックすることが必要です。
タイムラインで指定した時間範囲に対して、出力された静止画の枚数で割り算すれば、正確なフレーム間隔が得られます。結局パワーディレクタは、
MP4からの静止画計算を29.976fps相当の速度ではできないので、その時々のPCの負荷次第でフレームレートが変わってしまうのではないかと推測してます。VBで静止画ファイルの総数をカウントして、指定時間をいれて割り算させる処理をしないとモーションデータを同期できません。
●完成したプログラム
RTKモニターもついに、モーショングラフとモーション映像の同期解析機能がついたので、モニターではなく
アナライザーと名称を変更しようと思います。rev016以降はアナライザーという名称で呼びます。
参考までgistにアップしますが、作った私でさえ把握できないほど複雑ですので、部分部分を参考にしていただければと思います。
https://gist.github.com/dj1711572002/3189d7bf0c65e456a955c02132de28ff
※画面動画録画の画質
GEFORCEのグラフィックボードを使っている場合は、NVIDIAのGEFORCE Experienceという無料ソフトで
高画質な画面録画ができます。WINDOWS付属のXBOXの画面録画より綺麗です。
https://www.nvidia.com/ja-jp/geforce/geforce-experience/download/