【ImageJ】ImageJマクロを使ってみる
生命科学系研究者のえいこです。今回は、ImageJのマクロを使ってみようと思います。「マクロ」というとバグったり、動かなくなったりするのではないか?という不安があってなかなか触ったことがない人が多いのではないかと思います。私もそんなマクロ嫌いの一人でした。
しかし、マクロの組み方を知っているだけで仕事の効率がめちゃくちゃ良くなる、できることの幅が広がるなどのメリットが大きすぎたので、これを機会にしっかり勉強してみようと思っています。今回はImageJマクロの初歩の初歩、簡単なマクロの組み方からやっていこうと思います。
ImageJマクロとは?
スクリプトの一種。ImageJ上で働くスクリプト言語の一つです。マクロというとOffice、特にエクセルを思い浮かべる人が多いかもしれませんが、ImageJにも実はマクロが存在しています。
ImageJマクロが使えるとどうなるのでしょう?一番良く言われるのは、for文などを使って繰り返し処理が可能になるということです。この記事の最後の方で少しだけfor文をやろうと思いますが、まずは「繰り返し処理ができる様になるんだー」と言う感覚だけで大丈夫です。
生物系はプログラミング言語に親近感があまりないので、抵抗があるのではないかと思います。(私の場合はRを勉強してきたので、多少は抵抗感なく入れましたが...)
耳慣れない「変数」や「関数」と言った用語が出てきます。簡単に言うと「変数」は数学で使われる「変数」とかなり近い意味を持っていて、それを関数に代入すると関数を通して出力される値が変わっていきます。
エクセルを使っている人なら「関数」についてはそんなに説明はいらないかもしれません。「関数」は数学の様な数式の「関数」ではなく、私は「変換ボックス」というイメージを持っています。エクセルで説明すると、関数 ”SUM()”は総和を出力する箱。”SUM()”と言う箱の中に2,3,5,8などの数値を入れていくとそその総和である”18”と出力される仕組みになっています。ImageJマクロにも同じように「関数」が存在して、値を入れると変換してくれる様になっています。
では早速、画像内のあるピクセルの値を取得して書き換えてみましょう。
実際にImageJを動かしてみる
ImageJマクロの基本の「キ」、まずスクリプトを打つ画面を表示させてスクリプトを回してみましょう。
1. まずは、スクリプト画面を立ち上げてみます。
2. ImageJで動かせる言語はたくさんあるので言語を選びます。今回はマクロを使うので"IJ1 Macro"を選びます。
3. 実際にコードを書いてみます。今回書いたコードの解説はこちら↓
〜ある特定のピクセルの輝度を取ってくるコード〜
val = getPixel(100, 150);
print(val);
一行目の"val =~"は"val"という変数に"getPixel()"(関数)で取得した値を代入する操作をしています。"getPixel()"の()の中に、x座標、y座標を入れることでピクセルを指定することができます。
ImageJの画像の座標は、左上が(0, 0)で右に行けばx座標の値が一つずつ増えていきます。また、下に行けばy座標の値が一つづつ増えてきます。(右下のピクセルは(getWidth()-1, getHeight()-1)となります。)
〜〜
4. 上のコードを打って、スクリプト画面の"Run"を押すと ...
マクロが走って、Log画面に輝度が表示される
画像の特定の場所のピクセル値を書き換える
これで、ImageJマクロを開いて動かしてみるということに少し親近感がわいたのではないかと思います。では次に、画像のピクセル値を書き換えてみるということをしてみましょう。
「16 bit画像から8 bit画像に変換するときに気をつけること」の記事でも使った、「M51 GALAXY (177k, 16-bits)」のサンプル画像を使って変換していこうと思います。
1. 〜2.の手順でImageJマクロのスクリプト画面を開いて、言語をIJ1 Macroにしておきます。
6. ピクセル値を書き換えるコードを書いていきましょう。
〜ピクセル値を書き換えるコード〜
setPixel(100, 150, 30000);
updateDisplay();
“setPixel()”で座標の指定と、設定する輝度を指定します。括弧の中身は、(x座標, y座標, 設定する輝度)となっています。
“updateDisplay()”で設定した輝度を画像に反映させます。
〜〜
上の画像だとわかりにくいですが、1ピクセル分の値が変換されました。
簡単なfor文を使ってみる
最後に、for文を使って画像上のピクセル値を変換して水平な線を引いてみましょう。
1. 〜2.の手順でスクリプト画面を開いて、言語をIJ1 Macroにしておきます。
5. の手順でサンプル画像を開いておきましょう。
さてスクリプト画面にスクリプトを書いていきます。
〜連続でピクセル値を書き換えるコード〜
for (i = 0; i < getWidth(); i += 1){
setPixel(i, 150, 30000);
}
updateDisplay();
2行目の"setPixel()"は先ほども出てきた通り、指定した座標のピクセル値を変換する関数でした。
問題は1行目ですね。これが"for文"です!関数の中身(括弧の中)の数値のことを引数と言うのですが、その引数をみてみましょう。(繰り返し処理を何から始めるか?"i = 0", どこまで繰り返すか?"i < getWidth()", いくつづつ増やしていくか?(i += 1))なっています。また、繰り返し処理して欲しい内容は{}で囲うと言うルールになっているようです
二番目の引数の"getWidth()"は先ほども出てきましたが、画像の横幅が何ピクセルか返す関数です。画像の端は"0"なので"<"でイコールは入れなくて大丈夫です。
三番目の引数が少し厄介かもしれません。"i += 1"でループが増えるごとに1づつ増やしていくと言う意味になります。"i ++"と書かれることがありますが、これは"i += 1"が省略されたものなので、同じ意味です。
〜〜
コードを入力して、"Run"を押してみると...
水平に白い線が引けました!
これで、for文が書けるようになりましたね。
私はImageJマクロは食わず嫌いで避けていたのですが、少しだけ親近感が持てたような気がします。何事も始めの一歩を踏み出すのがなかなか難しいですよね。
少しずつ慣れていって、できることが増えていけば良いなと思っています。
次回は、もう少し難しいImageJマクロに挑戦してみようと思います。
それでは、また!
参考文献はこちら↓
『ImageJで始める生物画像解析』