VideoWriterについての質問です
Show older comments
フレームレート100の各画像上に10ミリ秒ごとのプロットを重ね、最終的にそれらを結合してアニメーションを作りたいのですが、いちいち各画像をimreadしてその時点に対応するプロットをhold onしてwriteVideoするというやり方だとループが膨大になり時間がかかってしまいます。
プロット結合画像をあらかじめcell配列などに格納してからwriteVideoするというようなやり方はありますでしょうか。ちなみにMatlab R2016aを使用しています。
参考までに私のスクリプトの一部を添付いたします。
*movieimgというcellにもとの画像ファイル名が格納されています。
savefn=['C:\Users\Desktop\Movie_File'];
v = VideoWriter(savefn);
v.FrameRate = 100;
open(v);
for t=1:length(movieimg)
imread(cell2mat(movieimg(t)));
hold on;
scatter(x,y,'r');
frame = getframe(gcf);
writeVideo(v,frame);
end
Answers (1)
Shunichi Kusano
on 27 Jun 2021
0 votes
複数フレームをまとめて書き込めるようですね。R2016だとこれできない、ということでしょうか。
メモリに収まりきる分だけのフレームを保持して書込み、をforで回せば良いかと思います。
6 Comments
KO
on 27 Jun 2021
Shunichi Kusano
on 28 Jun 2021
説明不足ですみません。
複数フレームをまとめて書き込むは、KOさんがされたいことそのままだと理解しています。「プロット結合画像をあらかじめcell配列などに格納してからwriteVideoする」の部分です。cellではなくて、getFrameで得られる構造体を、複数まとめてwriteVideoできます。詳細はリンクをご覧ください。
メモリに収まりきる分だけ、というのは100fpsの動画ということで、場合によっては動画一本分の画像データをメモリに保持できないかも、と思ったので加えた文言です。close さえしなければ動画ファイルにいくらでも追記できますので、例えば1000フレーム(10秒分)処理しておいてwriteVideo、そして次の1000フレーム処理してwriteVideo、という形で繰り返せばお手持ちのメモリに収まる範囲内で処理を書けます。
不明な点ありましたらお知らせください。
KO
on 28 Jun 2021
Shunichi Kusano
on 29 Jun 2021
Edited: Shunichi Kusano
on 30 Jun 2021
説明も大変なので、下記のようにコードを作ってみました。
が、まとめて数フレーム書き込むと逆に遅くなってしまいました。これは私も計算外です。現状解決策が思い浮かばないのですが、とりいそぎ共有いたします。
maxFrame = 100; % 全フレーム数
frameStep = 10; % 一時保存する画像データのフレーム数
v = VideoWriter('test','MPEG-4');
open(v);
f = figure; % figureを非表示で出す(描画分の計算時間節約)
imshow(rand(100,100));
s_frame = getframe(f);
s_frames = repmat(s_frame,[1 frameStep]); % 一時保存用の配列の準備
tic
for framei = 2:maxFrame % フレームごとに
% 保存する画像を作成
imshow(rand(100,100)); % ダミーデータ
frame_mod = mod(framei,frameStep);
if frame_mod > 0 % frameStep数分の保存を開始
s_frames(frame_mod) = getframe(f);
else
s_frames(frameStep) = getframe(f);
writeVideo(v,s_frames); % frameStep数分だけまとめて書込み
framei
end
end
toc
close(v);
% ちなみに下記が1フレームずつ書き込むテスト
v = VideoWriter('test','MPEG-4');
open(v);
f = figure; % figureを出す
tic
for framei = 2:maxFrame % フレームごとに
imshow(rand(100,100)); % ダミーデータ
writeVideo(v,getframe(f)); %
end
toc
close(v);
KO
on 30 Jun 2021
Shunichi Kusano
on 30 Jun 2021
バタバタしたときに回答したので、説明が少なくすみません。上のコードも一部訂正しました。
(figureのVisibleプロパティですが、offにしても大して実行時間は変わらずでした)
上のコードでわかりづらいところはif文のあたりかと思いますが、少し解説します。
frame_modはframei / frameStepを計算したときの余りです。frameiは現在何回目のfor文内実行か、frameStepは一時保存するフレーム数です。frameiはfor文繰り返しごとに2から3,4,5…と増えていきますが、余りも同じように2,3,4,5…と増えていきます。が、このときは、描画した画像のデータをどんどんs_framesに保存していきます。
frameiがframeStepで割り切れる数まで来ると、これまで保存してきたフレームデータを一気にまとめてwriteVideoします。
次のループではframe_modはまた1から2,3,4…と増えていくことになるので、s_framesに保存するだけとなり、またframeiがframeStepで割り切れる数まで来たら保存、と、これを繰り返して、必要なフレーム数maxFrameまで達したら終了、という流れとなります。文章だとわかりづらいと思いますが、コードと見比べながら咀嚼してみてください。
いま気付きましたが、上のコードですと、maxFrameがframeStepで割り切れないときは、最後の端数分の書込みが実行されないことになるので、elseif framei == maxFrameを足した方がいいですね。
Categories
Find more on Convert Image Type in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!