このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
イメージ取得と並列イメージ処理を実行
この例では、Web カメラからのイメージ取得とデータの後処理を並行して実行する方法を示します。
この例では、MATLAB クライアントはビデオ デバイスからフレームを取得し、後処理を並列ワーカーにオフロードします。これにより、ノイズ除去ニューラル ネットワークを使用して各フレームからノイズが除去されます。その後、フレームがビデオに書き込まれます。
この例では、parfeval
を使用してワーカーの後処理を実行し、parallel.pool.Constant
を使用して後処理中に使用するワーカーのノイズ除去ネットワークをインスタンス化します。ワーカーからフレームを戻し、フレームが順番に書き込まれるようにするため、この例では OrderedDataQueue
オブジェクトを使用しています。
デバイスの情報の抽出とビデオ出力の設定
以前のイメージ取得オブジェクトを消去し、現在マシンに接続されているビデオ デバイスの情報を抽出します。
objects = imaqfind;
delete(objects);
imaqreset;
deviceInfo = imaqhwinfo('winvideo')
deviceInfo = struct with fields:
AdaptorDllName: 'adaptor.dll'
AdaptorDllVersion: '6.1 (R2019b)'
AdaptorName: 'winvideo'
DeviceIDs: {[1]}
DeviceInfo: [1×1 struct]
出力ビデオのフォルダーが現在のディレクトリに既に存在するかどうかを確認します。出力ビデオのフォルダーが存在しない場合は、作成します。
if ~isfolder('OutputFolder') mkdir OutputFolder end
ビデオのデータを出力フォルダーの AVI ファイルに書き込むには、VideoWriter
オブジェクトを作成します。
videoOut = VideoWriter('OutputFolder/myVideo.avi');
並列環境の設定
後処理をワーカーにオフロードできるようにするには、まず並列プールを起動します。
p = parpool('Processes');
Starting parallel pool (parpool) using the 'Processes' profile ... Connected to parallel pool with 6 workers.
parallel.pool.Constant
オブジェクトを作成して、ワーカー内にノイズ除去ネットワークを 1 回だけ作成し、それを使用してフレームからノイズを除去します。
C = parallel.pool.Constant(@() denoisingNetwork('dncnn'));
後処理されたフレームをワーカーから戻し、順番に書き込むには、OrderedDataQueue
を使用します。afterEach
を使用して、フレームをディスクに書き込むためのコールバックを設定します。
Q = OrderedDataQueue; afterEach(Q,@(frame) writeVideo(videoOut,frame));
OrderedDataQueue
オブジェクトはこの例のサポート ファイルで定義されています。自分のコードで使用する場合は、コピーして他のファイルとともに配置します。
ビデオ入力オブジェクトの設定
ビデオ入力オブジェクトを作成します。このオブジェクトがクライアントでフレームごとに取得を実行するよう設定します。
videoIn = videoinput('winvideo',1,'YUY2_800x600')
Summary of Video Input Object Using 'Microsoft® LifeCam Cinema(TM)'. Acquisition Source(s): input1 is available. Acquisition Parameters: 'input1' is the current selected source. 10 frames per trigger using the selected source. 'YUY2_800x600' video data to be logged upon START. Grabbing first of every 1 frame(s). Log data to 'memory' on trigger. Trigger Parameters: 1 'immediate' trigger(s) on START. Status: Waiting for START. 0 frames acquired since starting. 0 frames available for GETDATA.
videoIn.ReturnedColorSpace = 'RGB';
videoIn.FramesPerTrigger = Inf;
videoIn.FramesAcquiredFcnCount = 1;
ビデオの書き込みフレーム レートを、ビデオの読み取りと同じレートに設定し、ビデオ出力オブジェクトを開きます。
src = videoIn.Source; videoOut.FrameRate = str2double(src.FrameRate); open(videoOut);
各フレームの取得後に後処理操作を開始するには、ビデオ入力オブジェクトの FramesAcquiredFcn
コールバックを定義してから取得を開始します。
videoIn.FramesAcquiredFcn = {@postProcessAndWrite,C,Q}; start(videoIn);
プレビュー ウィンドウを作成します。Figure ハンドル hPreviewFig
の waitfor
を使用して、プレビューを手動で閉じるとすぐにビデオを停止することができます。この例では、2 秒後にビデオ取得を停止します。
hPreviewImg = preview(videoIn);
hPreviewFig = ancestor(hPreviewImg,'figure');
pause(2);
stop(videoIn);
後処理関数により、future 変数がビデオ オブジェクトの UserData
プロパティに格納されます。この変数は、ビデオの書き込み操作の将来の実行を表します。すべてのデータを出力ファイルに書き込んだ後にビデオ ライターを閉じるには、この future 変数で afterAll
を使用します。
postProcessFutures = videoIn.UserData; closeVideoFuture = afterAll(postProcessFutures,@() close(videoOut),0);
この例の後処理操作は数分かかる場合があります。Windows 10、Intel® Xeon® W-2133 3.60 GHz CPU、コア数 6 の環境では、後処理は 4 分かかりました。
ウエイトバーを使用して後処理の進行状況を追跡できます。後処理操作が完了するたびにウエイトバーを更新するには、afterEach
を使用します。すべての操作が完了した後にウエイトバーを閉じるには、afterAll
を使用します。詳細については、afterEach と afterAll を使用したユーザー インターフェイスの非同期更新を参照してください。
h = waitbar(0,'Postprocessing...'); updateWaitbarFuture = afterEach(postProcessFutures, ... @(~) waitbar(sum(strcmp('finished',{postProcessFutures.State}))/numel(postProcessFutures),h), 1); afterAll(closeVideoFuture, @() close(h),0);
future 変数を待機することにより、書き込みが完了するまでクライアント セッションの実行をブロックします。
wait(closeVideoFuture);
完了したらビデオ入力オブジェクトを削除します。
delete(videoIn);
結果の可視化
ビデオ ファイルが作成されたら、結果を可視化することができます。
VideoReader
オブジェクトを使用してビデオ ファイルを読み取ります。
vidObj = VideoReader('OutputFolder/MyVideo.avi');
関数 readFrame
を使用して、一部のフレームを読み取ります。
images = cell(1,5); times = .4:.4:2; for ii = 1:numel(times) vidObj.CurrentTime = times(ii); images{ii} = readFrame(vidObj); end
フレームを可視化するには、関数 montage
を使用します。
montage(images,'Size',[1 5])
補助関数の定義
メインの後処理ルーティンを定義します。これはフレーム取得のたびに実行されます。この関数 postProcessAndWrite
は、データをビデオ入力オブジェクトから取得し、parfeval
を呼び出して、並列ワーカーでフレームのノイズ除去を開始します。
function postProcessAndWrite(videoIn,~,C,Q) [frame,~,metadata] = getdata(videoIn,1); postProcessFuture = parfeval(@postProcess,0,frame,C,Q,metadata.FrameNumber); videoIn.UserData = [videoIn.UserData postProcessFuture]; end
後処理関数をワーカーで実行するよう定義します。この例では、計算を単純にするために、各フレームをグレーに変換し、関数 denoiseImage
を使用してノイズを除去します。関数 postProcess
は、フレームと、parallel.pool.Constant
オブジェクトの Value
フィールドに格納されたノイズ除去ネットワークを、入力として使用します。ノイズ除去ニューラル ネットワークによるイメージのノイズ除去の詳細については、事前学習済みのイメージ ノイズ除去ネットワークの取得 (Image Processing Toolbox)を参照してください。
function postProcess(frame,C,Q,frameNumber) grayFrame = im2double(rgb2gray(frame)); denoisedGrayFrame = denoiseImage(grayFrame,C.Value); denoisedGrayFrame = im2uint8(denoisedGrayFrame); send(Q,frameNumber,denoisedGrayFrame) end
参考
parfeval
| parallel.pool.Constant
| imaqfind
(Image Acquisition Toolbox) | videoinput
(Image Acquisition Toolbox) | FramesAcquiredFcn | VideoWriter
| afterAll
| afterEach
| denoiseImage
(Image Processing Toolbox)
関連する例
詳細
- Image Processing Toolbox 入門 (Image Processing Toolbox)
- Get Started with Image Acquisition Toolbox (Image Acquisition Toolbox)