Image Acquisition Toolboxを用い​て顕微鏡のカメラから​画像を1分間隔で取得​し,pc内に保存する​方法について

7 views (last 30 days)
こちらのページ(https://jp.mathworks.com/help/imaq/acquiring-a-single-image-in-a-loop.html)を参考に,Image Acquisition Toolboxを用いて顕微鏡のカメラから画像を1分間隔で取得し,pc内に保存しようと試みたのですが画像が1枚しか取れませんでした.
vid = videoinput('winvideo', 1, 'RGB8_2752x2192');
preview(vid);
for i = 1:20
snapshot = getsnapshot(vid);
imagesc(snapshot);
end
顕微鏡から長時間(18~27時間程度),1分ごとに1枚画像を取得し続けるのはどのように行えばいいのでしょうか.
加えて,撮影した画像を外部アプリケーション(imagJ)などで動画化したいので,PCの内部メモリに保存したいです.
どなたかお力添えをいただければと思います.
よろしくお願いいたします.

Accepted Answer

Toru Ikegami
Toru Ikegami on 6 Sep 2021
こんにちは.
ぱっと思いつくのは,video input オブジェクトのタイマー機能を使用する方法でしょうか.
video input オブジェクトには,様々なタイミング(トリガー)で画像を取得するための機能が実装されています.今回は,次のような設定を行います.
  • マニュアルでトリガーをかける
  • トリガー1回につき画像を1枚取得
  • タイマー機能を使って,一定時間経過毎に「マニュアルトリガーを発生する関数(下記では mySnapshot)」を起動する.
vid = videoinput('winvideo',2,'MJPG_1024x576');
triggerconfig(vid,'manual');
vid.FramesPerTrigger = 1;
vid.TriggerRepeat = 5; % トリガ繰り返し数.この値を Inf に設定すると無限ループで画像を取得できます.
vid.TimerPeriod = 5; % 繰り返し周期を秒で指定します.1分間隔なら 60 です.
vid.TimerFcn = @mySnapshot;
また,データをメモリ上に保持されたいとの事でしたので,そのための仕掛けを仕込みます.やり方は色々ありますが,ここでは video input オブジェクトの UserData プロパティを使います.具体的には,フィールド imagescounts を持つ構造体を UserData とします.
% ビデオオブジェクトの UserData プロパティに画像データ保存用のバッファを設定
maxImageNumber = 10;
imageBuffer.images = repmat(uint8(0),[576 1024 3 maxImageNumber]);
imageBuffer.counts = 0;
imageBuffer.size = size(imageBuffer.images,4);
vid.UserData = imageBuffer;
ここまで準備したところで video input オブジェクトを走らせると,設定時間間隔で画像を取得し,UserData プロパティに保存してくれます.
start(vid);
trigger を既定の回数受け付けたら video input オブジェクトは自動的に停止します.TriggerRepeat の値を Inf に設定した場合には,マニュアルで停止する必要があります.
stop(vid);
記録されている画像を確認しましょう.どういうわけだか,vid.UserData.images といったドット表記の連鎖が上手く使えない(エラーになる)ので,getfield でバッファの内容を取得しています.
numFrames = vid.FramesAcquired;
imgData = getfield(vid.UserData,'images');
imgData = imgData(:,:,:,1:numFrames);
imshow(imtile(imgData));
関数 mySnapshot はこちら.
function mySnapshot(vid,~)
% トリガーをかけて画像を取得します.
trigger(vid);
img = getdata(vid,1);
% 画像バッファーを取得,カウンタをインクリメントして画像を保存します.
buffer = vid.UserData;
buffer.counts = buffer.counts + 1;
if buffer.counts <= buffer.size
buffer.images(:,:,:,buffer.counts) = img;
end
% ビデオオブジェクトの UserData を更新
vid.UserData = buffer;
end
  7 Comments
Toru Ikegami
Toru Ikegami on 9 Sep 2021
こんにちは.
まず,出力される動画の再生レートについては,ビデオライターオブジェクトのプロパティを設定することで変更できます.先に添付したmファイルの19行目がそれで,
vwObj.FrameRate = 1;
となっており,1秒に1フレーム再生する設定になっています.ここを次のように変更すると 30フレーム/秒 で再生するようになります.
vwObj.FrameRate = 30;
getdata 関数のタイムアウトの問題は少々手強いです.MATLAB Answers にもいくつか似たような事例が挙がっていて,決定的な解決策はなさそうです.
かなり古いエントリ(英語)ですが,
に書かれている対処方を試していただいて,解決できないようでしたらMathWorks のテクニカルサポートに連絡されることをお勧めします.その際に,お使いのカメラの型番,ファームウェアのバージョン,接続形態(USB,Ethernet, ... )などの情報をお伝えいただけるとスムーズに話が進むと思います.
卓真 小川
卓真 小川 on 9 Sep 2021
Edited: 卓真 小川 on 9 Sep 2021
タイムアウトの対処法の方,確認させていただきました.
1つ目のタイムアウトまでの時間を大幅に延長して行いましたが,やはりエラーが出てしましました.
2つ目の方法を試し,それでも解決しないようであればテクニカルサポートに問い合わせさせていただこうと思います.
getdataの前ということは以下のようなことでよろしいでしょうか?
function mySnapshot(vid,~)
% トリガーをかけて画像を取得します.
trigger(vid);
% 2つ目の方法の追加箇所
while get(vid,'FramesAvailable')<1 %Wait until at least 1 frame is available
unavailable=1;
end
frame = getdata(vid,1);
vwObj = vid.UserData;
writeVideo(vwObj,frame);
end

Sign in to comment.

More Answers (0)

Products


Release

R2021a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!