kentaPtの日記

主に画像解析のことなどの勉強記録として投稿します。もし何かございましたら、github (https://github.com/KentaItakura)などからご連絡いただけると幸いです。

argparseの使い方についてのメモ:MATLAB編

MATLABであれば、livescript、Pythonであれば jupyternotebook (lab)といった、対話型の開発環境を筆者は使うことが多いのですが、コマンドラインで、引数を指定して実行できるようにする機会も多くあります。そこで、MATLABPythonで、そのような指定(argparse)を使うときのメモを残します。

また、少し違う書き方もできて、そちらのほうが便利かもしれません。本記事のほかに以下のような方法もあります。

qiita.com

なお、本記事のコードやデータは以下のページに保存されています。

github.com

argparseの例

ここでは、以下のMATLABのセクションで用いる処理を例に説明します。findCat.mというMATLAB関数を作成し、それをコマンドラインMATLABの場合は、コマンドウィンドウ)で実行することを考えます。ここで使うコマンドの例は以下の通りです。

findCat('./testImage/cat.jpg');
findCat('./testImage/cat.jpg',5);
findCat('./testImage/cat.jpg',10,'Opacity',0.1,'shape','circle');

ここで、以下のように、入力の画像だけを指定して実行してみます。

findCat('./testImage/cat.jpg');

以下の動画のように、ウィンドウが表示されて、何かを囲むように指示されます。例えば、猫の顔を囲んでみましょう。薄く、指定した範囲が黄色で囲まれたことがわかります。

次は、以下のコマンドを実行してみます。

findCat('./testImage/cat.jpg',10,'Opacity',0.1,'shape','circle');

指定された範囲が、丸で囲まれました。

次に、cat.jpgのあとの値を大きくしてみます。

findCat('./testImage/cat.jpg',40,'Opacity',0.1,'shape','circle');

円の枠線が太くなりました。どうやら、この値を大きくすると、枠線が太くなるようです。

次は、shapeの後の値をfilledRectangleに変更してみます。次は、中身が色塗りされた長方形で囲まれました。

findCat('./testImage/cat.jpg',1,'Opacity',0.1,'shape','filledRectangle');

最後に、Opacityの値を0.8にしてみます。

findCat('./testImage/cat.jpg',1,'Opacity',0.8,'shape','filledRectangle');

透明度が下がり、より濃い黄色の長方形が作成されました。

argparseを試してみた結果

このように、コマンドラインの引数を変えることで、挿入する図形の形状を変更をしたり、幅や透明度をカスタマイズすることができました。コードの中身そのものを変えるのではなく、コマンドで変えるだけなので、運用も簡単になりそうです。

argparseについてもう少し詳しく

以下のコマンドをもう一度見てみます。10という値は、画像のパスの後に来ていて、特にどういうパラメーターなのかは、コマンド上では明示していません。一方、Opacityや、shapeといったパラメーターを宣言してから引数を入力する部分も確認できます。前者のほうは、特にパラメーターを宣言する必要がないので、コマンドがシンプルになります。調整するパラメーターが少ない場合は、便利ですが、パラメーターの数が多いと、非常にたくさん値が並び、混乱を招きます。'Opacity'などと宣言する場合は、これらを書く手間はありますが、どのパラメータを調整しているのかわかりやすいです。

findCat('./testImage/cat.jpg',10,'Opacity',0.1,'shape','circle');

コーディングについて

おおまかには以下のようなステップで進みます。コード中にコメントを入れていて、今後は、これをフォーマットとしてコピーアンドペーストし、変数の名前などを変えていくとよいでしょう。

1 各パラメーターのデフォルトの値の設定 2 inputParser変数の作成 3 パラメーターの定義 4 各パラメーターの値の読み取り

function imgOut = findCat(img,varargin)
   % デフォルト(既定)の値の設定
   defaultOpacity = 0.1;
   defaultLineWidth = 5;
   defaultShape = 'rectangle';
   % 選択肢を設定することもできる
   expectedShapes = {'circle','rectangle','FilledRectangle'};
   
   % inputParser変数の作成
   p = inputParser;
   % 変数が数値であり、かつ0より大きいことを確認する関数を定義する
   validScalarPosNum = @(x) isnumeric(x) && isscalar(x) && (x > 0);
   % 画像のパス @ischarにて、文字型であることを確認する
   addRequired(p,'img',@ischar);
   addOptional(p,'LineWidth',defaultLineWidth,validScalarPosNum);
   addParameter(p,'Opacity',defaultOpacity,validScalarPosNum);
   addParameter(p,'shape',defaultShape,@(x) any(validatestring(x,expectedShapes)));
   parse(p,img,varargin{:});
   % 各パラメーターを変数に格納する
   img = p.Results.img;
   LineWidth = p.Results.LineWidth;
   Opacity = p.Results.Opacity;
   ShapeName = p.Results.shape;
   
   % 画像の読み込みと表示
   I = imread(img);
   figure;imshow(I)
   % 図の上で囲む範囲を指定する
   rect = getrect();
   title('図の上で囲む範囲を指定してください')
   
   % 挿入する図形の種類に応じて、処理をスイッチする
   switch ShapeName
       case 'circle'
           % 描く円の中心と半径を定義する
           centroid = [rect(1)+rect(3)/2,rect(2)+rect(4)/2,rect(3)/2];
           % 円の挿入
           imgOut = insertShape(I,'Circle',centroid,'Opacity',Opacity,'LineWidth',LineWidth);
       case 'rectangle'
           % 長方形の挿入
           imgOut = insertShape(I,'FilledRectangle',rect,'Opacity',Opacity,'LineWidth',LineWidth);
       otherwise
           % 色が塗られた長方形の挿入
           print('FilledRectangle')
           imgOut = insertShape(I,'FilledRectangle',rect,'Opacity',Opacity,'LineWidth',LineWidth);
   end

   %イメージを表示
   figure;imshow(imgOut);

end