1. 程式人生 > >影象分析之直方圖分析

影象分析之直方圖分析

  - created by gloomyfish

影象分析之強度直方圖分析

直方圖介紹

強度直方圖圖形化顯示不同的畫素值在不同的強度值上的出現頻率,對於灰度影象來說強度

範圍為[0~255]之間,對於RGB的彩色影象可以獨立顯示三種顏色的強度直方圖。強度直方

圖是用來尋找灰度影象二值化閾值常用而且是有效的手段之一,如果一幅灰度影象的直方圖

顯示為兩個波峰,則二值化閾值應該是這兩個波峰之間的某個灰度值。同時強度直方圖是調

整影象對比度的重要依據

直方圖實現方法:

對一幅灰度影象從上到下,從左到右掃描每個畫素值,在每個灰度值上計算畫素數目,以這

些資料為基礎完成影象直方圖的繪製。

執行效果如下:


程式實現:

1.      首先對一幅RGB影象完成灰度轉換,轉換程式碼如下:

2.      初始化直方圖資料陣列int[256] 因為灰度值的範圍為0~255

3.      掃描灰度影象,完成強度資料計算。

4.      使用Java 2D繪製直方圖

直方圖實現原始碼:

package com.gloomyfish.image.analysis;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

public class HistogramAnalysisAlg {
	private BufferedImage srcImage;
	private BufferedImage histogramImage;
	private int size = 280;
	
	public HistogramAnalysisAlg(BufferedImage srcImage){
		histogramImage = new BufferedImage(size,size, BufferedImage.TYPE_4BYTE_ABGR);
		this.srcImage = srcImage;
	}
	
	public BufferedImage getHistogram() {
        int[] inPixels = new int[srcImage.getWidth()*srcImage.getHeight()];
        int[] intensity = new int[256];
        for(int i=0; i<intensity.length; i++) {
        	intensity[i] = 0;
        }
        getRGB( srcImage, 0, 0, srcImage.getWidth(), srcImage.getHeight(), inPixels );
        int index = 0;
        for(int row=0; row<srcImage.getHeight(); row++) {
        	int ta = 0, tr = 0, tg = 0, tb = 0;
        	for(int col=0; col<srcImage.getWidth(); col++) {
        		index = row * srcImage.getWidth() + col;
        		ta = (inPixels[index] >> 24) & 0xff;
                tr = (inPixels[index] >> 16) & 0xff;
                tg = (inPixels[index] >> 8) & 0xff;
                tb = inPixels[index] & 0xff;
                int gray = (int)(0.299 * (double)tr + 0.587 * (double)tg + 0.114 * (double)tb);
                intensity[gray]++;
        	}
        }
        
        // draw XY Axis lines
        Graphics2D g2d = histogramImage.createGraphics();
        g2d.setPaint(Color.BLACK);
        g2d.fillRect(0, 0, size, size);
        g2d.setPaint(Color.WHITE);
        g2d.drawLine(5, 250, 265, 250);
        g2d.drawLine(5, 250, 5, 5);
        
        // scale to 200
        g2d.setPaint(Color.GREEN);
        int max = findMaxValue(intensity);
        float rate = 200.0f/((float)max);
        int offset = 2;
        for(int i=0; i<intensity.length; i++) {
        	int frequency = (int)(intensity[i] * rate);
        	g2d.drawLine(5 + offset + i, 250, 5 + offset + i, 250-frequency);
        }
        
        // X Axis Gray intensity
        g2d.setPaint(Color.RED);
        g2d.drawString("Gray Intensity", 100, 270);
		return histogramImage;
	}
	
	private int findMaxValue(int[] intensity) {
		int max = -1;
		for(int i=0; i<intensity.length; i++) {
			if(max < intensity[i]) {
				max = intensity[i];
			}
		}
		return max;
	}

	/**
	 * A convenience method for getting ARGB pixels from an image. This tries to avoid the performance
	 * penalty of BufferedImage.getRGB unmanaging the image.
	 */
	public int[] getRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) {
		int type = image.getType();
		if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB )
			return (int [])image.getRaster().getDataElements( x, y, width, height, pixels );
		return image.getRGB( x, y, width, height, pixels, 0, width );
    }

	/**
	 * A convenience method for setting ARGB pixels in an image. This tries to avoid the performance
	 * penalty of BufferedImage.setRGB unmanaging the image.
	 */
	public void setRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) {
		int type = image.getType();
		if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB )
			image.getRaster().setDataElements( x, y, width, height, pixels );
		else
			image.setRGB( x, y, width, height, pixels, 0, width );
    }

}

測試程式碼如下:
package com.gloomyfish.image.analysis;  
  
import java.awt.Dimension;  
import java.awt.Graphics;  
import java.awt.Graphics2D;  
import java.awt.MediaTracker;  
import java.awt.image.BufferedImage;  
import java.io.File;  
import java.io.IOException;  
  
import javax.imageio.ImageIO;  
import javax.swing.JComponent;  
import javax.swing.JFileChooser;  
import javax.swing.JFrame;  
  
public class ImageAnalysisUI  extends JComponent {  
    /** 
     *  
     */  
    private static final long serialVersionUID = 1518574788794973574L;  
    private BufferedImage rawImg;  
    private BufferedImage modImg;  
    private MediaTracker tracker;  
    private Dimension mySize;  
      
      
    public ImageAnalysisUI(File f) {  
        try {  
            rawImg = ImageIO.read(f);  
            HistogramAnalysisAlg filter = new HistogramAnalysisAlg(rawImg);  
            modImg = filter.getHistogram();  
        } catch (IOException e1) {  
            e1.printStackTrace();  
        }  
          
        tracker = new MediaTracker(this);  
        tracker.addImage(rawImg, 1);  
          
        // blocked 10 seconds to load the image data  
        try {  
            if (!tracker.waitForID(1, 10000)) {  
                System.out.println("Load error.");  
                System.exit(1);  
            }// end if  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
            System.exit(1);  
        }// end catch  
          
        mySize = new Dimension(2*rawImg.getWidth() + 20, rawImg.getHeight()*2);  
        JFrame imageFrame = new JFrame("Gloomyfish - Image Analysis");  
        imageFrame.getContentPane().add(this);  
        imageFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
        imageFrame.pack();  
        imageFrame.setVisible(true);  
    }  
      
    public void paint(Graphics g) {  
        Graphics2D g2 = (Graphics2D) g;  
        g2.drawImage(rawImg, 0, 0, rawImg.getWidth(), rawImg.getHeight(), null);  
        g2.drawImage(modImg, rawImg.getWidth()+10, 0, modImg.getWidth(), modImg.getHeight(), null);  
        g2.drawString("source image", 10, rawImg.getHeight() +10);  
        g2.drawString("connected component labeled area", 10 + modImg.getWidth(), rawImg.getHeight() +10);  
    }  
    public Dimension getPreferredSize() {  
        return mySize;  
    }  
      
    public Dimension getMinimumSize() {  
        return mySize;  
    }  
      
    public Dimension getMaximumSize() {  
        return mySize;  
    }  
      
    public static void main(String[] args) {  
        JFileChooser chooser = new JFileChooser();  
        chooser.showOpenDialog(null);  
        File f = chooser.getSelectedFile();  
        new ImageAnalysisUI(f);  
    }  
}