カメラを手軽に高度に制御したいときに、MATLAB Image Acquisition Toolboxは便利なツールだと思われています。しかし、その対価も有していることからあなたは目を背けてはいけません。関数の数こそ少ないですが、その仕様をきちんと理解していないと、あなたは自分で気づかないうちに落とし穴に落ちていることでしょう。
この記事では、撮影タイミングをカメラに指示するためのTriggerの前に空いている穴と、その回避方法について解説します。
記事の流れ
・取り扱う問題点と筆者の環境
・解決するコードの書き方
・コードの書き方の論拠
##取り扱う問題点と筆者の環境
・MATLAB 2020a
・Image Acquisition Toolbox
・Image Acquisition Toolbox Support Package for GenICam Interface
・windows機
・研究用カメラ(秘匿)
####問題点 triggerの後に、カメラがrunning状態ではなくなっている。
ちなみに、Triggerを使うシーンにはどのようなものがあるでしょうか。
たとえば、高速でカメラのシャッターを切りたいという需要を考えてみましょう。一枚一枚撮影するたびにパソコンへ読み出すのではなく、たくさん撮ってから一度に読み出すことで、カメラの読み出し時間を考慮せずシャッタースピードを変更できます。
これは、MATLAB Image Acquisition Toolbox のtrigger と getdata を使用することで実装できます。
ちょっと実装してみましょう
% 間違い例です
vid = videoinput('Camera name', 'option');
src = getselectedsource(vid);
vid.FramesPerTrigger = 1;
Triggerconfig = (vid,'manual');
src.ExpousureTime = 5000;
start(vid);
trigger(vid);
pause(0.01);
trigger(vid);
pause(0.01);
trigger(vid);
getdata(vid,3);
stop(vid);
delete(vid);
clear vid
% これは間違い例です
こうすれば、カメラの読み出し時間が50 msであろうとも、10 ms毎に露光時間5000 usで撮像できます。
しかしながら、これでは動きません。2つ目のtriggerに対してエラーメッセージ「カメラがrunning状態ではありません」が出てきます。
必要最低限の指示さえすれば動くものと思っていたのですが、何か足りないようです。これでは高級言語の名折れです。
なかなか問題を解決できないと、ここまでの悪態をつくような精神状態に追い込まれます。そうならないうちに、続きを読みましょう。
##解決するコードの書き方
start(vid)の前に vid.TriggerRepeat = Inf を追加します。
vid = videoinput('Camera name', 'option');
src = getselectedsource(vid);
vid.FramesPerTrigger = 1;
Triggerconfig = (vid,'manual');
src.ExpousureTime = 5000;
vid.TriggerRepeat = Inf;
start(vid);
trigger(vid);
pause(0.01);
trigger(vid);
pause(0.01);
trigger(vid);
getdata(vid,3);
stop(vid);
delete(vid);
clear vid
##論拠
そんなことはMATLAB documentationのrunningやtriggerには書かれていません。
documentationの中では、startの中に関連する記述があります。
https://jp.mathworks.com/help/imaq/start.html?s_tid=srchtitle
以下、documentationからの引用
An image acquisition object stops running when one of the following conditions is met:
The stop function is issued.
The requested number of frames is acquired. This occurs when
FramesAcquired = FramesPerTrigger * (TriggerRepeat + 1)
where FramesAcquired, FramesPerTrigger, and TriggerRepeat are properties of the video input object.A run-time error occurs.
The object's Timeout value is reached.
と書いてあります。
FramesAcquiredというのは、startしてから撮ったframeの数を数えている変数です。
重要なのは、デフォルトが TriggerRepeat = 0 であることです。
https://jp.mathworks.com/help/imaq/triggerrepeat.html?s_tid=srchtitle (TriggerRepeatのdocumentation)
この値を Infに設定してしまえば、憂うことはなにもないということですね。(本当かな?)
・Trigger一回までは許容される
・startとTriggerRepeatに分散して記述がある
あたりが沼ポイントでしょうか
余談
ちなみに、startとtriggerをひたすら繰り返すことでも解決できますが、カメラのほうに余裕があればの話です。
私が使ったカメラと環境では、このコードだと2回目のstartでMATLABがクラッシュしました。
startのMATLAB documentationの記述ですが、imaq(toolboxのファイル内)にあるstart.mのコメント欄にも
同じような記述が見られます。筆者は、documentationを見つける前にこちらの記述に当たりました。
デフォルトが0になっている意味ですが、おそらく「意図しない無限ループを避ける」目的があるのかと思います。
##追記ログ