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

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

Javaで画像にROIを置き、輝度値を測定する。

ここでは、ROIで囲んだ領域の輝度値を求めるプログラムを書く。

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.event.MouseInputAdapter;

public class ROImeasure extends JFrame implements ActionListener {

	BufferedImage img;
	DataBuffer buf;
	MyPanel1 mypane1;
	int intData [];
	int h;
	int w;
	int x0;
	int xEnd;
	int deltaX;
	int y0;
	int yEnd;
	int deltaY;
	int counter = 0;
	
	//画像を開く
	public void OpenImage () {
		try {
			File openFile = new File("開く画像ファイル");
			img = ImageIO.read(openFile);
			h = img.getHeight();
			w = img.getWidth();
			buf = img.getRaster().getDataBuffer();
		} catch (IOException ex) {
			System.out.println("miss");
		}
		
		//画像をフレームに貼る
		JFrame imgFrame = new JFrame ("Open Image");
		imgFrame.setBounds (300, 100, w, h);
		imgFrame.setVisible(true);
		mypane1 = new MyPanel1 (w, h);
		imgFrame.getContentPane().add(mypane1, BorderLayout.CENTER);
	}
////////////////////
	
	//画像を張り付ける用のツール
	public class MyPanel1 extends JPanel {
		public MyPanel1 (int width, int height) {
			setSize(width, height);
		}
		
		public void paintComponent (Graphics g) {
			g.drawImage(img, 0, 0, this);
		}
	}
////////////////////////
	
	//ROIを描く
	public void roiDraw () {
		mypane1.addMouseListener (new MouseCheck());
		mypane1.addMouseMotionListener(new MouseCheck());
	}
	
	//ROIの始点と終点を取得
	class MouseCheck extends MouseInputAdapter {
		
		//マウスが押された点を取得
		public void mousePressed(MouseEvent e) {
			x0 = e.getX();
			y0 = e.getY();
		}
		
		//マウスが離された点を調べる
		public void mouseReleased (MouseEvent e) {
			if (counter == 0) {
			Graphics g = mypane1.getGraphics();
			xEnd = e.getX();
			yEnd = e.getY();
			g.drawLine(x0, y0, x0, yEnd);
			g.drawLine(x0, y0, xEnd, y0);
			g.drawLine(x0, yEnd, xEnd, yEnd);
			g.drawLine(xEnd, y0, xEnd, yEnd);
			counter++;
			}
		}
	}
	
	//ROIで囲まれた領域の輝度値を取得
	public void roiMeasure () {
		//x0, y0, xEnd, yEndの並び替え
		if (x0 > xEnd) {
			int k = x0;
			x0 = xEnd;
			xEnd = k;
		}
		if (y0 > yEnd) {
			int k = 0;
			y0 = yEnd;
			yEnd = k;
		}
		
		//ROIの幅の取得
		deltaX = xEnd - x0;
		deltaY = yEnd - y0;
		
		//ROIの輝度値を入れる配列を定義
		intData = new int [deltaX*deltaY];
		
		//輝度値の取得
		int no = 0;
		int sum = 0;
		for (int i = y0; i < yEnd; i++) {
			for (int j = x0; j < xEnd; j++) {
				intData [no] = buf.getElem(j);
				sum = sum + intData[no];
				no++;
			}
		}			
		
		//ROIのデータの出力
		System.out.println();
		System.out.println("Area = " + deltaX*deltaY);
		System.out.println("輝度値の平均は : " + sum/(deltaX*deltaY));
	}
	
	public void actionPerformed (ActionEvent e) {
		String cmd = e.getActionCommand();
		
		if (cmd.equals("open")) {
			counter = 0;
			OpenImage();
		} else if (cmd.equals("roi")) {
			roiDraw();
		} else if (cmd.equals("measure")) {
			roiMeasure();
		}
	}
	
	ROImeasure (String title) {
		setTitle (title);
		setBounds (10, 10, 200, 190);
		setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
		
		JButton button = new JButton ("Open");
		JButton button1 = new JButton("ROI");
		JButton button2 = new JButton ("Measure");
		button.addActionListener (this);
		button1.addActionListener (this);
		button2.addActionListener (this);
		button.setActionCommand("open");
		button1.setActionCommand("roi");
		button2.setActionCommand("measure");
		button.setBounds(40, 10, 100, 30);
		button1.setBounds(40, 60, 100, 30);
		button2.setBounds(40, 110, 100, 30);
		JPanel pane = new JPanel ();
		pane.setLayout(null);
		pane.add(button);
		pane.add(button1);
		pane.add(button2);
		getContentPane().add(pane, BorderLayout.CENTER);
	}
	
	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		ROImeasure frame = new ROImeasure ("Test");
		frame.setVisible(true);
	}
}

上記プログラムで、下の図のように画像上にROIを作製した。
f:id:Aki-Miya:20150215153000p:plainf:id:Aki-Miya:20150215153008p:plain
そして、コンソール上にROIで囲んだ領域の面積と輝度値が下記のように表示された。

Area = 25619
輝度値の平均は : 197

このサンプルを画像解析ソフトであるImageJでも解析し、同様の結果が得られた。このことから、このプログラムもきちんとワークしているようである。

今回もROIを1つだけ書きたかったため、counterでROIの個数を制限した。