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

14 Ansichten (letzte 30 Tage)
卓真 小川
卓真 小川 am 6 Sep. 2021
Bearbeitet: 卓真 小川 am 9 Sep. 2021
こちらのページ(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の内部メモリに保存したいです.
どなたかお力添えをいただければと思います.
よろしくお願いいたします.

Akzeptierte Antwort

Toru Ikegami
Toru Ikegami am 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 Kommentare
Toru Ikegami
Toru Ikegami am 9 Sep. 2021
こんにちは.
まず,出力される動画の再生レートについては,ビデオライターオブジェクトのプロパティを設定することで変更できます.先に添付したmファイルの19行目がそれで,
vwObj.FrameRate = 1;
となっており,1秒に1フレーム再生する設定になっています.ここを次のように変更すると 30フレーム/秒 で再生するようになります.
vwObj.FrameRate = 30;
getdata 関数のタイムアウトの問題は少々手強いです.MATLAB Answers にもいくつか似たような事例が挙がっていて,決定的な解決策はなさそうです.
かなり古いエントリ(英語)ですが,
に書かれている対処方を試していただいて,解決できないようでしたらMathWorks のテクニカルサポートに連絡されることをお勧めします.その際に,お使いのカメラの型番,ファームウェアのバージョン,接続形態(USB,Ethernet, ... )などの情報をお伝えいただけるとスムーズに話が進むと思います.
卓真 小川
卓真 小川 am 9 Sep. 2021
Bearbeitet: 卓真 小川 am 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

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Produkte


Version

R2021a

Community Treasure Hunt

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

Start Hunting!