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


初めに

Imagej Pluginを作るときにモジュール的に使えるものやピットフォール的なものを備忘録目的に残していくシリーズ(続く予定はあまりない)。
※実際には試していない部分・メソッドが一部あります。
今回はParticleAnalyzerについてです。

ParticleAnalyzerて何さ

ImageJのAnalyze Particles...から起動できるやつのjava class名です。

Analyze Particlesについて

このコマンドでは、バイナリー(白黒二値化された)画像または閾値設定された画像で、対象物の数を数え、計測する。このコマンドで行われていることは、画像全体または選択範囲をスキャンし、対象物の境界を探す。見つけるとワンドツールで対象物の輪郭を囲み、Measure (計測)コマンドで計測を行う。測定済みの対象物は塗りつぶして見えなくしてから次のスキャンに戻り、画像または選択範囲の端に到達するまで画像内をスキャンしていく。この過程を中断したいときは、[esc] キーを押す。画像に閾値を設定するには、Imageメニュー>Adjust>Threshold (閾値設定)を使う。
ImageJ 日本語情報より

API documentでAnalyze Particlesとかで検索しても出てこない件

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

宣言

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

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で定義されています。
多くはここで説明されている。

定義 説明
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自体はふつうに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をセットするといいかもしれない。

計算前の準備メソッド

お好きなものを。

準備
//設定用ダイアログを表示する。多分キャンセルを押すと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かけたほうが無難

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

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

終わりに

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

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

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

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