ImageJ pluginを作る。備忘的な各論～ParticleAnalyzer～

#初めに
Imagej Pluginを作るときにモジュール的に使えるものやピットフォール的なものを備忘録目的に残していくシリーズ(続く予定はあまりない)。
※実際には試していない部分・メソッドが一部あります。
今回は[ParticleAnalyzer](https://imagej.nih.gov/ij/developer/api/ij/ij/plugin/filter/ParticleAnalyzer.html)についてです。


##ParticleAnalyzerて何さ
ImageJの`Analyze Particles...`から起動できるやつのjava class名です。

Analyze Particlesについて
>このコマンドでは、バイナリー（白黒二値化された）画像または閾値設定された画像で、対象物の数を数え、計測する。このコマンドで行われていることは、画像全体または選択範囲をスキャンし、対象物の境界を探す。見つけるとワンドツールで対象物の輪郭を囲み、Measure （計測）コマンドで計測を行う。測定済みの対象物は塗りつぶして見えなくしてから次のスキャンに戻り、画像または選択範囲の端に到達するまで画像内をスキャンしていく。この過程を中断したいときは、[esc] キーを押す。画像に閾値を設定するには、Imageメニュー＞Adjust＞Threshold （閾値設定）を使う。
[ImageJ 日本語情報](https://seesaawiki.jp/w/imagej/d/ImageJ%a5%de%a5%cb%a5%e5%a5%a2%a5%eb%a1%a7Analyze%a1%ca%b2%f2%c0%cf%a1%cb%a5%e1%a5%cb%a5%e5%a1%bc)より

~~[API document](https://imagej.nih.gov/ij/developer/api/ij/module-summary.html)でAnalyze Particlesとかで検索しても出てこない件~~

二値化した画像から、粒子を検出し、それぞれの形や場所、大きさの分析ができるやつですね。早速使い方を見ていきます。

##宣言
以下のようにコンストラクタが定義されています。

```java:Constructor
//デフォルトのコンストラクタ
//Default constructor
ParticleAnalyzer()

//真円率のカットオフはデフォルト(0～1:真円率で足切りしない)
//Constructs a ParticleAnalyzer using the default min and max circularity values (0 and 1).
ParticleAnalyzer​(int options, int measurements, ResultsTable rt, double minSize, double maxSize)
//Constructs a ParticleAnalyzer.
ParticleAnalyzer​(int options, int measurements, ResultsTable rt, double minSize, double maxSize, double minCirc, double maxCirc)	
```

それぞれのオプションについて見ていきます。オプションが~~面倒~~実行時に設定が必要なら一番上のコンストラクタで宣言して、`実行前`で紹介している`showDialog()`を使うといいんじゃないかと。
###options
result画面を表示するか、やRoiマネージャに値を入れていくか、などの設定をする。
ParticleAnalyzer内で定数として定義されています。

|定義|値|説明|
|:-:|:-:|:-|
|SHOW_RESULTS|1|結果をresultウィンドウに書き出す|
|SHOW_SUMMARY|2|合計や総面積などをSummaryウィンドウに書き出す(非推奨)|
|SHOW_OUTLINES|4|輪郭を描いた画像を描き出す|
|EXCLUDE_EDGE_PARTICLES|8|ウィンドウの端に接するものは無視する|
|SHOW_ROI_MASKS|16|検出範囲をマスク画像に変換する、それぞれの画素値はRoiのIDになる|
|SHOW_PROGRESS|32|プログレスバーを表示するようだ|
|CLEAR_WORKSHEET|64|Resultウィンドウを初期化してから処理を開始する|
|RECORD_STARTS|128|検索で最初に見つけた場所を記録する(ResultsTableに書き出す)|
|DISPLAY_SUMMARY|256|合計や総面積などをSummaryウィンドウに書き出す|
|SHOW_NONE|512|何も表示しない|
|INCLUDE_HOLES|1024|穴の中を埋める(ドーナツの中を埋める感じ)|
|ADD_TO_MANAGER|2048|Roiマネージャーに加える|
|SHOW_MASKS|4096|0/255のマスク画像を表示する|
|FOUR_CONNECTED|8192|自動選択ツールのアルゴリズム設定(多分繋がりやすくなる)|
|IN_SITU_SHOW|16384|マスク画像で元画像を置き換えるらしいが、多分機能してない|
|SHOW_OVERLAY_OUTLINES|32768|結果(輪郭)を元画像にオーバーレイ表示する|
|SHOW_OVERLAY_MASKS|65536|結果(マスク画像)を元画像にオーバーレイ表示する|
|COMPOSITE_ROIS|131072|多分ドーナツの中を埋めない感じかなと|
|OVERLAY|262144|オーバーレイで表示するのフラグ？？詳細不明だが輪郭がオーバーレイされた|


ちなみに重複する項目については**ROI_MASKS < OVERLAY_OUTLINES < OVERLAY_MASKS < OUTLINES < MASKS < NOTHING**の優先順の可能性が高いです。(ソースコード内でこの順番でif~チェックしており、下の行のチェックで上の行のチェックに上書きしている)

###measurements
Set Measurements...で選択する項目。
`ij.measure.Measurements`で定義されています。
多くは[ここ](https://imagej.nih.gov/ij/docs/menus/analyze.html)で説明されている。

|定義|値|説明|
|:-:|:-:|:-|
|ALL_STATS|全部の合計|全部選択|
|AREA|1|面積(Area)|
|MEAN|2|平均値(Mean)|
|STD_DEV|4|偏差(StdDev)|
|MODE|8|最頻値(Mode)|
|MIN_MAX|16|最小値・最大値(Min,Max)|
|CENTROID|32|重心(X,Y)|
|CENTER_OF_MASS|64|画素値で重みづけした重心(XM,YM)|
|PERIMETER|128|周長(Perim.)|
|LIMIT|256|Thresholdされた点のみ計算対象にする？|
|RECT|512|バウンディングボックスの左上座標、幅、高さ(BX,BY,Width,Height)|
|LABELS|1024|対象画像のタイトル|
|ELLIPSE|2048|フィットする楕円の長径、短径、傾き(Major,Minor,Angle)|
|INVERT_Y|4096|画像の左下を原点とする？指定しても変化なし？|
|CIRCULARITY|8192|円らしさ(Circ.、AR、Round、Solidity))|
|Circ.|真円度|4π*面積/周囲長^2|
|AR|アスペクト比|長径/短径|
|Round|真円度|4*面積/(π*長径^2)|
|Solidity|堅牢性|面積/凸面面積(Edit>Selection>Convex Hullで得られるRoi)|
|SHAPE_DESCRIPTORS|8192||
|FERET|16384|フェレー径:輪郭上の任意の2点でもっとも離れている距離、およびそれに直行する最長径(Feret,FeretX,FeretY,FeretAngle,MinFeret)|
|INTEGRATED_DENSITY|0x8000|輝度の総和(IntDen,RawDen)|
|IntDen|算出値|面積*平均輝度|
|RawDen|実測値|ピクセル値の総和|
|MEDIAN|0x10000|中央値|
|SKEWNESS|0x20000|歪度(平均輝度の3次モーメント)(Skew)google|
|KURTOSIS|0x40000|尖度(平均輝度の4次モーメント)(Kurt)翻訳|
|AREA_FRACTION|0x80000|面積率(%Area)Threadで赤い部分or0でない画素の割合|
|SLICE|0x100000|何スライス目か(Slice)|
|STACK_POSITION|0x100000|スタック位置(Ch、Slice,Frame)|
|SCIENTIFIC_NOTATION|0x200000||
|ADD_TO_OVERLAY|0x400000||
|NaN_EMPTY_CELLS|0x800000||;||
いつも通りわからないところは空欄

###ResultsTable
結果を入れる表。[ResultsTable](https://imagej.nih.gov/ij/developer/api/ij/ij/measure/ResultsTable.html)自体はふつうにImageJのAPIとして定義されているので
`ResultsTable rt = new ResultsTable()`とかってしてこのrtを変数としていれてやればいい。ij.measureがimportされているかには注意。

###minSize, maxSize, minCirc, maxCirc
最小サイズ下限、最大サイズ上限、真円度の上下限(0.0~1.0)。真円度の指定は義務ではない(デフォルトは0.0~1.0)
サイズ上限は画像のwidth*heightの値とかDouble.POSITIVE_INFINITYをセットするといいかもしれない。

##計算前の準備メソッド
お好きなものを。

```java:準備
//設定用ダイアログを表示する。多分キャンセルを押すとfalseが返る。
boolean showDialog();

//ResultsTable,RoiManager,SummaryTableをセットする。必要なものを。
static void	setResultsTable​(ResultsTable rt);
static void	setRoiManager​(RoiManager manager);
static void	setSummaryTable​(ResultsTable rt);

//フォントサイズや表示線の幅に関する設定。お好みで。
static void	setLineWidth​(int width);
static void	setFontSize​(int size);
static void	setFontColor​(java.lang.String color);

//結果画像を表示したくないときにTrueをセット
void setHideOutputImage​(boolean hideOutputImage);
//結果画像を取得する。ShowメニューでNoneを選択しているとNullが返るのでNullチェックはしたほうがよさそう。
ImagePlus getOutputImage();
```

##実行
※実行前にThresholdかけたほうが無難

```java:実行
//対象の画像を送り込む。StackだったらIamgePlusのsetSliceとか使うといいと思う。
boolean analyze​(ImagePlus imp);

//実行に持ってきたものの、これがどう動作するのかよくわからない。analyzeだけで事足りると思う。
//void run​(ImageProcessor ip);
```

##終わりに
あとはセットしていたRoiManagerからRoiを取得したりResultsTableから結果を取得したりでしょうか。このRoiManagerと連携させてRoiを取得するのがまた面倒というか難しいというかだったりする。
RoiManagerだと、パッと見た感じこの辺りをこんな感じですかねぇ、コンストラクタ自信ないです。

```java:RoiManager
//コンストラクタ:ROI Managerウィンドウを開く/関連付ける
RoiManager();
//コンストラクタ：ウィンドウを開かないで
RoiManager(false)

//Roiの個数を返す
int getCount();
//Roiを配列で返す
Roi[] getRoisAsArray();

```

ParticleAnalyzerは設定の多さがそのまま面倒臭さにつながっている気もするけど、ここら辺のパラメータを調節したら自動でやってくれるというのはいいですよね。