生物屋さんのためのゼロからのプログラミング

―忘れないための覚書 (たま~に更新)―

EclipseでImageJのPlugin作成 -マウスでクリックした場所にOval ROIを描く-

ここでは、ダイアログを使って画像を開き、画像のマウスをクリックした場所にOval ROIを描くプラグイン: ROI_Maker を作った。

ソースコードは下記。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import ij.IJ;
import ij.ImagePlus;
import ij.gui.ImageCanvas;
import ij.gui.OvalRoi;
import ij.io.OpenDialog;
import ij.plugin.PlugIn;
import ij.plugin.frame.RoiManager;

public class ROI_Maker implements PlugIn, MouseListener, MouseMotionListener, ActionListener{

	ImagePlus imp;
	ImageCanvas ic;
	RoiManager rm;

	int rRoi;  //描くROIの大きさ
	int counter;  //ROIの個数をカウント
	JTextField rVal; //描くROIの大きさを入力する用

	//ファイルをダイアログを使って開く
	public void openFile () {
		OpenDialog od = new OpenDialog("Select");
		String directory = od.getDirectory();
		String name = od.getFileName();
		String path = directory + name;
		imp = IJ.openImage(path);
		imp.show();
        ic = imp.getCanvas();  //ImageCanvasにImageを渡す
	}

	//Roiを置けるようにする。
	public void activeROI () {
		ic.addMouseListener(this);
		ic.addMouseMotionListener(this);

		//Roi Managerを立ち上げる
		rm = new RoiManager();
		rm.runCommand(imp, "Show All");
		rm.runCommand(imp, "Show All with labels");

		rRoi = Integer.parseInt(rVal.getText());
		counter = 0;
	}

	//コントローラーの作成
	public void run (String arg) {
		JFrame frame = new JFrame ("Controller");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setBounds(10, 10, 200, 100);
		frame.setVisible(true);

		JButton openButton = new JButton ("Open");
		JButton roiButton = new JButton ("ROI");
		JLabel rLabel = new JLabel ("Roi size = ");
		rVal = new JTextField("30");
		openButton.addActionListener(this);
		roiButton.addActionListener(this);
		openButton.setActionCommand("Open");
		roiButton.setActionCommand("Roi");
		openButton.setBounds(40, 10, 90, 30);
		roiButton.setBounds(40, 50, 90, 30);
		rLabel.setBounds(40, 90, 90, 30);
		rVal.setBounds(105, 90, 40, 30);

		JPanel pane = new JPanel();
		pane.setLayout(null);
		pane.add(openButton);
		pane.add(roiButton);
		pane.add(rLabel);
		pane.add(rVal);
		frame.getContentPane().add(pane, BorderLayout.CENTER);
	}

	//ボタンが押された時の動作
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO 自動生成されたメソッド・スタブ
		String cmd = e.getActionCommand();
		if(cmd.equals("Open")) {
			openFile();
		} else if (cmd.equals("Roi")) {
			activeROI();
		}
	}

    //クリックした場所にOvalRoiを描く
	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO 自動生成されたメソッド・スタブ
		int x = ic.offScreenX(e.getX());
		int y = ic.offScreenY(e.getY());
		imp.setRoi(new OvalRoi(x-rRoi/2, y-rRoi/2, rRoi, rRoi));
		rm.addRoi(imp.getRoi());

		//ROIの名称変更
		rm.select(counter);
		rm.runCommand("Rename", String.valueOf(counter+1));
		counter++;
	}

	//クリックした場所にROIを描く
	@Override
	public void mousePressed(MouseEvent e) {
		// TODO 自動生成されたメソッド・スタブ
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO 自動生成されたメソッド・スタブ
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO 自動生成されたメソッド・スタブ
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO 自動生成されたメソッド・スタブ
	}



	@Override
	public void mouseDragged(MouseEvent e) {
		// TODO 自動生成されたメソッド・スタブ
	}

	@Override
	public void mouseMoved(MouseEvent e) {
		// TODO 自動生成されたメソッド・スタブ
	}
}

これを実行すると、
f:id:Aki-Miya:20180105105052p:plain
このように、Pluginに「ROI Maker」が追加される。

この「ROI Maker」をクリックすると、
f:id:Aki-Miya:20180105105603p:plain
このようなGUIが立ち上がる。
Openボタンをクリックすると、ダイアログが立ち上がり、画像を選択できる。
そして、ROIボタンをクリックすると、「Roi Manager」が立ち上がり、ROIを描けるようになる。

描くROIの大きさは、「ROI size = 」の横のJTextFieldに入力できる。(ここでは初期値を30とした)
(注:このソースコードではROIボタンを押すと、JTextFieldの値が読み込まれるので、ROIの大きさを変える場合はROIボタンを押す前に書き換える。)

そして、実際に画像にROIを描いたのが下。(ImageはFijiに入っている”Clown (14K)”を使用)
f:id:Aki-Miya:20180105111348p:plain
f:id:Aki-Miya:20180105111406p:plain
予定通り、Roi ManagerにROIがaddされている。


ImageJのPluginのソースコードを書くには、Fijiの「Records...」を使用して、コードの使い方を見るのが楽。
Fijiの
[Plugins -> Macros -> Records...] で 「Recorder」を立ち上げる。
「Record:」の横のボックスから「Java」を選択。
あとは実際にやりたい作業を行い、そのlogを参考にしてコードを描く。(丸々コピーしてもダメ)


個々のコードを見ていく。

public class ROI_Maker implements PlugIn, MouseListener, MouseMotionListener, ActionListener{

マウスの動きを見るように「MouseListener」「MouseMotionListener」を、ボタンを押した時に仕事をするように「ActionListener」を実装した。
ここでは「PlugIn」を実装しているが、「PlugInFilter」や「PlugInFrame」との使い分け方を僕はまだ理解していない。

//ファイルをダイアログを使って開く
	public void openFile () {
		OpenDialog od = new OpenDialog("Select");
		String directory = od.getDirectory();
		String name = od.getFileName();
		String path = directory + name;
		imp = IJ.openImage(path);
		imp.show();
        ic = imp.getCanvas();  //ImageCanvasにImageを渡す
	}

もっと楽な方法がありそうだが、とりあえずstack画像もこのコードで開けた。

	//Roiを置けるようにする。
	public void activeROI () {
		ic.addMouseListener(this);
		ic.addMouseMotionListener(this);

		//Roi Managerを立ち上げる
		rm = new RoiManager();
		rm.runCommand(imp, "Show All");
		rm.runCommand(imp, "Show All with labels");

		rRoi = Integer.parseInt(rVal.getText());
		counter = 0;
	}

ここで、Roi Managerを立ち上げている。置いたROIを表示したままにし、さらにラベルを付けるために、

	rm.runCommand(imp, "Show All");
	rm.runCommand(imp, "Show All with labels");

とした。

   rRoi = Integer.parseInt(rVal.getText());

この部分で、描くROIの大きさを取得している。

    counter = 0;

これは、ただ単にROIに番号を振る用。

  //クリックした場所にOvalRoiを描く
	public void mouseClicked(MouseEvent e) {
		// TODO 自動生成されたメソッド・スタブ
		int x = ic.offScreenX(e.getX());
		int y = ic.offScreenY(e.getY());
		imp.setRoi(new OvalRoi(x-rRoi/2, y-rRoi/2, rRoi, rRoi));
		rm.addRoi(imp.getRoi());

		//ROIの名称変更
		rm.select(counter);
		rm.runCommand("Rename", String.valueOf(counter+1));
		counter++;
	}

マウスの位置座標を得るには、

	int x = e.getX();
	int y = e.getY();

でも得られる。しかし、画像が拡大・縮小した場合、欲しい画像上の座標ではなく、拡大・縮小された画像での座標を取得することになる。そのため、ここでは下記の

	int x = ic.offScreenX(e.getX());
	int y = ic.offScreenY(e.getY());

を使用した。

imp.setRoi(new OvalRoi(”x座標”, ”y座標”, ”int a(横幅)”, ”int b(縦幅)”));

は、(x, y)座標から”int a”の横幅、”int b”の縦幅を持つ正方形 (長方形) に内接する円 (楕円) を描くメソッド。
そのため、下記のようにして

   imp.setRoi(new OvalRoi(x-rRoi/2, y-rRoi/2, rRoi, rRoi));

クリックした場所に、半径 rRoi/2のOval Roiを描けるようにした。

	rm.addRoi(imp.getRoi());

ここで、Roi Managerに上記で描いたROIを登録している。

      //ROIの名称変更
	rm.select(counter); 
	rm.runCommand("Rename", String.valueOf(counter+1));
	counter++;

ここで、名称を変更するROIをRoi Managerから選び、

	rm.runCommand("Rename", String.valueOf(counter+1));

で、intである”counter”を”String”に変換し、ROIに通し番号を付けられるようにした。


このPluginを走らせるためには、前の記事
EclipseでImageJのPlugin作成 -下準備編 ver.2- - 生物屋さんのためのゼロからのプログラミングで「TESTPlugin_」を作成した時と同様に、「build.xml」を作成する。基本的には、「TESTPlugin_」を新しいPlugin名に変更するだけでいい。一度デバッグしてしまえば、2回目以降の実行は「実行構成...」から出来る。

但し、「実行構成...」をクリックして現れる下記のウインドウで、
f:id:Aki-Miya:20180105122153p:plain
メインタブのプロジェクト名が「IJ」で、メイン・クラスが「ij.ImageJ」になっているかの確認と、ソースタブ内で実行するプロジェクトが選ばれているかの確認を忘れずに。