1. 程式人生 > >獲取圖片每個畫素點的RGB並計算灰度值

獲取圖片每個畫素點的RGB並計算灰度值

主要通過獲取本地的一張圖片,分析圖片每一畫素點的RGB值,由此獲得每一畫素點的灰度值,並對這些灰度值進行熵的計算。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JMenuBar;
import javax.swing.ImageIcon;
import javax.swing.JPanel;


public class ImageTest {
	public static void main(String args[]) {
		new MyFrame();
	}
}

class MyFrame extends JFrame{
	JPanel panel = null;
	JLabel label = null;
	
	JPanel panel2 = null;
	JLabel label2 = null;
	
	public MyFrame(){
		super("測試圖片灰度值的熵值");
		this.setBounds(400,100, 400, 400);
		this.setBackground(Color.gray);
		
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				setVisible(false);
				System.exit(0);
			}
		});
		
		JMenu fileMenu = new JMenu("選擇圖片");
		JMenuItem openItem = new JMenuItem("開啟");
		openItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				openFile();
			}
		}) ;
		
		fileMenu.add(openItem);
		JMenuBar bar = new JMenuBar();
		bar.add(fileMenu);
		this.setJMenuBar(bar);
		
		this.panel = new JPanel();
		this.label = new JLabel();
		label.setText("請選擇一張圖片!");
		panel.add(label);
		
		this.panel2 = new JPanel();
		this.label2 = new JLabel();
		panel2.add(label2);
		
		this.add(panel, BorderLayout.CENTER);
		this.add(panel2, BorderLayout.SOUTH);
		
		this.setVisible(true);
		this.setResizable(true);
	}
	
	public void openFile() {
		JFileChooser  chooser = new JFileChooser();
		chooser.showOpenDialog(this);
		File f = chooser.getSelectedFile();
		//檔案是否存在或者是否選擇
		if(f == null) {
			return;
		}
		
		BufferedImage bi = null;
		try {
			bi = ImageIO.read(f);
			/*獲取檔案是否為圖片,如果能夠正常的獲取到一張圖片的寬高屬性,
			那肯定這是一張圖片,因為非圖片檔案我們是獲取不到它的寬高屬性的*/
			if(bi == null || bi.getHeight() <=0 || bi.getWidth() <=0){
				label.setText("您選擇的不是一張圖片,請從新選擇!");
				return;
			} else {
				calculate(bi);
				String path = f.getPath();
				ImageIcon image = new ImageIcon(path);
				label.setIcon(image);			//設定JLabel的顯示圖片
				label.setText("");
				this.pack();
				validate();				//使有效
			}
		} catch (IOException e) {
//			e.printStackTrace();
			return;
		}
		
	}
	
	public void calculate(BufferedImage bi) {
		int sgray[] = new int[256];
		for(int i=0; i<256; i++) {
			sgray[i] = 0;
		}
		
		double sum = 0;
		
		int width = bi.getWidth();
		int height = bi.getHeight();
		
		for(int i=0; i<width; i++) {
			for(int j=0; j<height; j++) {
				int rgb = bi.getRGB(i, j);
				
				/*應為使用getRGB(i,j)獲取的該點的顏色值是ARGB,
				而在實際應用中使用的是RGB,所以需要將ARGB轉化成RGB,
				即bufImg.getRGB(i, j) & 0xFFFFFF。*/
				int r = (rgb & 0xff0000) >> 16;
				int g = (rgb & 0xff00) >> 8;
				int b = (rgb & 0xff);
				int gray = (int)(r * 0.3 + g * 0.59 + b * 0.11);	//計算灰度值
				sgray[gray] ++;
			}
		}
		
		for(int i=0; i<256; i++) {
			if(sgray[i] != 0) {
				double p = sgray[i] * 1.0 / (width * height);	//每一灰度值出現的概率
				sum += p * (Math.log(1/p) / Math.log(2));		//熵
			}
		}

		String result = "該圖片的灰度值的熵為:" + sum;
		label2.setText(result);				//設定JLabel的顯示文字
		validate();
	}
}


java對RGB的值進行轉換時有偏差,怎樣才能減少或者消除這個偏差呢?求指教。。

前面所說的偏差,通過牛人的指教,已經得到改正。主要是將calculate()這個方法進行了更改。用Raster獲取圖片的畫素。因為要看影象的型別,看看它是多少位的.如果是32位就要考慮aphal值通道,通過Raster物件來讀取/寫入畫素,
它將自動幫你處理成為32位的.

下面附上更改部分的程式碼:

public void calculate(BufferedImage bi) {
		int sgray[] = new int[256];
		for(int i=0; i<256; i++) {
			sgray[i] = 0;
		}
		
		double sum = 0;
		
		int width = bi.getWidth();
		int height = bi.getHeight();
		
		Raster ra = bi.getData();	
		/*影象的型別,看看它是多少位的.如果是32位
		的要考慮aphal值通道,通過Raster物件來讀取/寫入畫素,
		它自動幫你處理成為32位的. */
		
		/*Rectangle rect = ra.getBounds();
		int w = (int) rect.getWidth();
		int h = (int) rect.getHeight();*/
//System.out.println(width + ":" + height);
//System.out.println(w + ":" + h);
		
		int pixels[] = new int[width * height];
		pixels = ra.getPixels(0, 0, width, height, pixels); //獲得圖片每個點的畫素
		
		for(int i=0; i<width; i++) {
			for(int j=0; j<height; j++) {
				//int rgb = bi.getRGB(i, j);
				int rgb = pixels[i * j];
				
				/*應為使用getRGB(i,j)獲取的該點的顏色值是ARGB,
				而在實際應用中使用的是RGB,所以需要將ARGB轉化成RGB,
				即bufImg.getRGB(i, j) & 0xFFFFFF。*/
				int r = (rgb & 0xff0000) >> 16;
				int g = (rgb & 0xff00) >> 8;
				int b = (rgb & 0xff);
				int gray = (int)(r * 0.3 + g * 0.59 + b * 0.11);	//計算灰度值
				sgray[gray] ++;
			}
		}