low level programmer

« 測試用的 GeneralEAO,... | Main | JAI - 色階分佈 Histogram »
星期日 八月 24, 2008

JAI - BandCombine 處理

description

在看 Histogram 的時候發現有個東西搞不懂就是 BandCombine.
沒上過圖學的課, 所以不懂 Band 要怎麼解釋.
在看過 api doc 之後再觀察一下總算有點概念, 但也都是猜的.
希望有學過的人能分享一下, 感謝.

reference

jaistuff
BandCombineDescriptor

Example

使用 bandCombine 首先要指定一個陣列. 這個陣列 size 是規定好的.
double[][] matrix = new double[destBands][sourceBands + 1];
sourceBands 是來源圖的 band, destBands 目地圖的 band. 這個 band 可以透過 RenderedImage 呼叫 RenderedImage.getSampleModel().getNumBands(); 取得.
我測 jpg, png 都是 3.
指定好後, BandCombine 會透過 api 上寫的公式計算
// s = source pixel
// d = destination pixel
for(int i = 0; i < destBands; i++) {
    d[i] = matrix[i][sourceBands];
    for(int j = 0; j < sourceBands; j++) {
        d[i] += matrix[i][j]*s[j];
    }
}
這個公式其實蠻單純的,
假如你指定 matrix 是
{
    {0.5,0.6,0.7,0.1}
}     
這是候原圖的像素 [0,0] 的值為 [101.0, 81.0, 48.0]
這樣套在公式上,
s[] = {101, 81, 48} 
destBands = 1
sourceBands = 3
計算過程就是
matrix = {0.5,0.6,0.7,0.1}
i = 0 => d[0] = matrix[0][3] = 0.1
  j = 0 => d[0] = d[0] + matrix[0][0] * s[0] =  0.1 + 0.5 * 101 =  50.6
  j = 1 => d[0] = d[0] + matrix[0][1] * s[1] = 50.6 + 0.6 *  81 =  99.2
  j = 2 => d[0] = d[0] + matrix[0][2] * s[2] = 99.2 + 0.7 *  48 = 132.8 (final)

所以 [0,0] 在 BandCombine 之後就變成 [132.8], 然後在讀取 SampleModel 的 Data 時發現好像有四捨五入就變 133.
如果陣列改為
{
    {0.5,0.6,0.7,0.1},
    {0.2,0.3,0.4,0.8}
};
上面已經算出第一個陣列值的結果是 132.8, 接下來再算第二個陣列.
matrix = {0.2,0.3,0.4,0.8}
i = 0 => d[0] = matrix[0][3] = 0.1
  j = 0 => d[0] = d[0] + matrix[0][0] * s[0] =  0.8 + 0.2 * 101 = 21.0
  j = 1 => d[0] = d[0] + matrix[0][1] * s[1] = 21.0 + 0.3 *  81 = 45.3
  j = 2 => d[0] = d[0] + matrix[0][2] * s[2] = 45.6 + 0.4 *  48 = 64.8    
最後第二組陣列計算結果會讓像素 [0,0] 的值變成 [132.8, 64.8], 然後 RenderedImage.getSampleModel().getData() 的結果可看到像素 [0,0] = [133,65]
在這裡就不討論 [132.8] 和 [132.8, 64.8] 以及如果有更多的數字在這個陣列裡面代表什麼意思, 那是其他的 issue 了, 現在也不會, 只能猜這應該是 Red, Green, Blue 的值, 如果是(132.8, 64.8) 可能是 Red=132.8, Green=64.8 吧?
附上測試程式
public class JAITester {

    private PlanarImage doHistogram(PlanarImage imageToHistogram) {
        int numBands = imageToHistogram.getSampleModel().getNumBands();
        double[][] matrix = new double[][]{
            {0.5,0.6,0.7,0.1},
            {0.2,0.3,0.4,0.8}
        };
        pixelToFile(new File("build/beforeBandCombine.txt"), imageToHistogram);
        ParameterBlock pb = new ParameterBlock();
        pb.addSource(imageToHistogram);
        pb.add(matrix);
        imageToHistogram = JAI.create("bandcombine", pb, null);
        pixelToFile(new File("build/afterBandCombine.txt"), imageToHistogram);
        return imageToHistogram;
    }

    private void pixelToFile(File outputFile, RenderedImage img) {
        StringBuffer sb = new StringBuffer();
        int w = img.getWidth();
        int h = img.getHeight();
        for ( int x = 0; x < w; x++ ) {
            for ( int y = 0; y < h; y++ ) {
                sb.append("[" + x + ", " + y + "]:[");
                double[] pixel = img.getData().getPixel(x, y, (double[])null);
                for ( int i = 0; i < pixel.length; i++ ) {
                    
                    if ( i == pixel.length - 1 ) {
                        sb.append( pixel[i] );
                    } else {
                        sb.append( pixel[i] + ", " );
                    }
                }
                sb.append("]");
            }
            sb.append("\n");
        }
        try {
            FileWriter f = new FileWriter(outputFile);
            f.write(sb.substring(0));
            f.flush();
            f.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(JAITester.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(JAITester.class.getName()).log(Level.SEVERE, null, ex);
        }         
    }

    /** 
     * http://forums.java.net/jive/message.jspa?messageID=221209
     * this gets rid of exception for not using native acceleration */
    static {
        System.setProperty("com.sun.media.jai.disableMediaLib", "true");
    }
    
    private static final String IMG_FILE_1 = "test1.jpg";

    public static void main(String[] args) {
        JAITester test = new JAITester();
        test.test();
    }

    private void test() {
        PlanarImage input = JAI.create("fileload", IMG_FILE_1);
        JPanel jPanelMain = new JPanel(new MigLayout("", "grow", "grow"));
        jPanelMain.add(new JScrollPane(new DisplayJAI(input)), "grow");
        jPanelMain.add(new JScrollPane(new DisplayJAI(doHistogram(input))), "grow");
        show(jPanelMain);
    }

    private void show(JComponent comp) {
        JFrame f = new JFrame();
        f.setLocation(50, 50);
        f.setPreferredSize(new Dimension(800, 600));
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.getContentPane().add(comp);
        f.pack();
        f.setVisible(true);
    }
}    

迴響:

發表迴響:
  • HTML 語法: 關閉