獲取圖片每個畫素點的RGB並計算灰度值
阿新 • • 發佈:2019-02-16
主要通過獲取本地的一張圖片,分析圖片每一畫素點的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] ++; } }