videoWriterによる動画出力の高速化について
이 질문을 팔로우합니다.
- 팔로우하는 게시물 피드에서 업데이트를 확인할 수 있습니다.
- 정보 수신 기본 설정에 따라 이메일을 받을 수 있습니다.
오류 발생
페이지가 변경되었기 때문에 동작을 완료할 수 없습니다. 업데이트된 상태를 보려면 페이지를 다시 불러오십시오.
이전 댓글 표시
0 개 추천
対象物の自動検出と追従する動画解析を行っています。解析して対象物に色を塗ったり、線を書き加えるなどして動画出力をしています。
動画出力する際に、どうしても時間を要すために、高速化の方法があればご教授ください。
以下の方法は実践済です。
・フレームレイト調整
・MPEG-4での出力
・画像の縮小
★「imshow」を行うことに時間がかかっているのですが、これは外せないでしょうか・・・
★解析結果(対象物の座標)の取得のみまず行い、動画の作成は後で行うために別変数で保存する方法などもあればお教えください。
% 解析動画読み込み
vidObj = VideoReader("video.mp4");
% 出力動画ファイル
VideoWriter(strcat('trackSoftAlphaVer2_',sprintf(filename)),
% 1frameずつ読み込み&解析
while hasFrame(vidObj)
img = readFrame(vidObj);
~~~~~~~~~~~~~~~~~~~~~
% imgに対する解析
% 目標物の座標(X, Y)を算出
% 画像内の直線の軌跡(Line)を算出
~~~~~~~~~~~~~~~~~~~~~
figure('Visible', 'off');
imshow(img); hold on
scatter(X, Y);
plot(Line);
hold off
vidImg = getframe(gcf);
writeVIdeo(outVideo, vidImg);
end
채택된 답변
Kojiro Saito
2024년 10월 17일
1 개 추천
プロファイラーをかけてみたところ、imshowとgetframe、そしてfigureの処理時間が掛かっています。

現在のコードでは画像を表示してからscatterとplotをおこなっているので、getframeで画像を取得する必要があり、imshowも必要になります。figureは毎回作成する必要ないので、これをwhileの外に置くだけで処理時間がかなり速くなります。
figure('Visible', 'off');
% 1frameずつ読み込み&解析
while hasFrame(vidObj)
% TODO
end
また、Computer Vision Toolboxを使用できるならinsertShapeとinsertMarkerでplotとscatterに近いことができ、画像上に直接描けるのでより高速に実現できます。
vidObj = VideoReader("xylophone_video.mp4");
% 出力動画ファイル
outVideo = VideoWriter("out4.mp4", "MPEG-4");
open(outVideo)
figure('Visible', 'off');
% 1frameずつ読み込み&解析
while hasFrame(vidObj)
img = readFrame(vidObj);
%~~~~~~~~~~~~~~~~~~~~~
% imgに対する解析
% 目標物の座標(X, Y)を算出
% 画像内の直線の軌跡(Line)を算出
%~~~~~~~~~~~~~~~~~~~~~
X = randi(100);
Y = randi(100);
RGB = insertMarker(img, [X Y], "circle", MarkerColor="b");
lineData = reshape([0:100 0:100], [], 2);
RGB = insertShape(RGB, "line", lineData, ShapeColor="b");
writeVideo(outVideo, RGB);
end
close(outVideo)
댓글 수: 10
プロファイラーまでかけていただきありがとうございます。
とてもよく理解できるとともに勉強になりました。
1)insert~の使用に関してですが、表出しているグラフの軸ラベルやメモリ等にかなり設定を加えています。そのような場合でもinsert~で対応できる範疇でしょうか?
2)上記の関係でscatterの前に、axes関数を入れているのですが、「figure('Visible', 'off');」 をfor文の外に出すと、グラフのみが動き、imgが更新されません。対応策ございますでしょうか?
Kojiro Saito
2024년 10월 18일
inserTextで画像にテキストを挿入でき、軸ラベルの代替はできますが、等間隔の目盛りを書くのは大変だと思います。従来通りimshow、hold onとgetframeでおこなったほうが良さそうです。
Kojiro Saito
2024년 10월 18일
HanaHana
2024년 10월 18일
insertTextについて、分かりました。
drawnow limitrateでは、imgの更新がされませんでした。もし他にアイデアございましたら試してみたいと思いますので、引き続きご助言お願いいたします。
Kojiro Saito
2024년 10월 18일
imshowは引き続き入れていますでしょうか?
下記のサンプルではimshowでimgの更新がされています。
vidObj = VideoReader("xylophone_video.mp4");
% 出力動画ファイル
outVideo = VideoWriter("out.mp4", "MPEG-4");
open(outVideo)
figure('Visible', 'off');
% 1frameずつ読み込み&解析
while hasFrame(vidObj)
img = readFrame(vidObj);
X = randi(100);
Y = randi(100);
imshow(img);
hold on
scatter(X, Y);
plot(0:100, 0:100)
hold off
vidImg = getframe(gcf);
writeVideo(outVideo, vidImg);
end
close(outVideo)
お伝えする情報が不足しておりました。
重ね合わせるグラフが複雑かつ軸の操作を加える関係で以下のようになっております。
while hasFrame(vidObj)
img = readFrame(vidObj);
X = randi(100);
Y = randi(100);
imshow(img);
hold on
scatter(X, Y); % img全体に書き込み
ax = axes('Position', [~,~,~,~,]); % グラフは画面右側に配置するためその位置を指定
plot(0:100, 0:100); % グラフに書き込むデータ⓵
hold on % グラフに書き込むデータが複数あるので、ここで改めてhold on
plot(0:100, 0:200); グラフに書き込むデータ⓶
ax.Color = 'r';
ax.XLabel.String = "time";
hold off
vidImg = getframe(gcf);
writeVideo(outVideo, vidImg);
end
axesを使ったところでなにかおかしくなっているでしょうか。
Kojiro Saito
2024년 10월 20일
편집: Kojiro Saito
2024년 10월 20일
画像を表示する座標軸と、グラフを表示する軸が2つあるため、hold onだけではうまく画像の描画更新ができていないようです。hold(ax1, 'on')とhold(ax1, 'off')のようにどちらの座標軸を固定するのか指定してみてください。
下記のコードで動作確認できました。グラフの座標軸を毎回作ると時間が掛かるので、axes(fig, 'Position', [])をwhileループの外に置いています。
% 解析動画読み込み
vidObj = VideoReader("xylophone_video.mp4");
% 出力動画ファイル
outVideo = VideoWriter("out5.mp4", "MPEG-4");
open(outVideo)
tic
fig = figure('Visible', 'off');
ax1 = gca;
ax2 = axes(fig, 'Position', [0.7, 0.7, 0.2, 0.2]); % グラフは画面右側に配置するためその位置を指定
while hasFrame(vidObj)
img = readFrame(vidObj);
X = randi(100);
Y = randi(100);
imshow(img, Parent = ax1);
hold(ax1, 'on')
scatter(ax1, X, Y); % img全体に書き込み
hold(ax1, 'off')
% グラフは画面右側に配置するためその位置を指定
plot(ax2, 0:100, 0:100); % グラフに書き込むデータ⓵
hold(ax2, 'on') % グラフに書き込むデータが複数あるので、ここで改めてhold on
plot(ax2, 0:100, 0:2:200); %グラフに書き込むデータ⓶
hold(ax2, 'off')
ax2.Color = 'r';
ax2.XLabel.String = "time";
vidImg = getframe(gcf);
writeVideo(outVideo, vidImg);
end
t = toc
close(outVideo)
HanaHana
2024년 10월 23일
返信が遅くなり申し訳ありません。
お示しいただいた方法で無事に描画更新ができました。
ただ、imgの画像サイズがこれまでよりも小さくなってしまいます。感覚的に75%くらい?
これまではできあがった動画画面いっぱいにimgが表示されていたのが、周りに白い余白ができてしまいます。
動画全体に対するグラフの位置は変わりません。こちらも対応策ありましたらご助言ください。
Kojiro Saito
2024년 10월 24일
座標軸 (axes)がFigure に対して余白を持つためですね。
参考: 座標軸のレイアウトの制御
ax1 を定義するところで、Positionプロパティで開始位置を0、横幅と縦幅を1に設定してFigure の全領域を使うように設定してみてください。
%ax1 = gca;
ax1 = axes(fig, 'Position', [0, 0, 1, 1]);
ax2 = axes(fig, 'Position', [0.75, 0.75, 0.2, 0.2]);
ax2 の位置がやや左寄りになってしまうので、こちらのPosition の値も調整してみました。
HanaHana
2024년 10월 25일
無事にサイズが安定しました。
幅広い領域にわたりご助言ありがとうございました。勉強になりました。
추가 답변 (0개)
카테고리
도움말 센터 및 File Exchange에서 Video Formats and Interfaces에 대해 자세히 알아보기
참고 항목
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!웹사이트 선택
번역된 콘텐츠를 보고 지역별 이벤트와 혜택을 살펴보려면 웹사이트를 선택하십시오. 현재 계신 지역에 따라 다음 웹사이트를 권장합니다:
또한 다음 목록에서 웹사이트를 선택하실 수도 있습니다.
사이트 성능 최적화 방법
최고의 사이트 성능을 위해 중국 사이트(중국어 또는 영어)를 선택하십시오. 현재 계신 지역에서는 다른 국가의 MathWorks 사이트 방문이 최적화되지 않았습니다.
미주
- América Latina (Español)
- Canada (English)
- United States (English)
유럽
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)