IntegralImage.java

package ac.essex.ooechs.imaging.commons.fast; 
 
import ac.essex.ooechs.imaging.commons.PixelLoader; 
 
import java.io.File; 
import java.io.IOException; 
 
/** 
 * 
 * <p> 
 * Integral image allows you to make a precalculated image which can then be used 
 * to very quickly establish the sum of pixels in any rectangular area. 
 * </p> 
 * 
 * <p/> 
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License 
 * as published by the Free Software Foundation; either version 2 
 * of the License, or (at your option) any later version, 
 * provided that any use properly credits the author. 
 * This program is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU General Public License for more details at http://www.gnu.org 
 * </p> 
 * 
 * @author Olly Oechsle, University of Essex, Date: 20-Sep-2007 
 * @version 1.1 
 */ 
public class IntegralImage { 
 
    protected PixelLoader image; 
    protected int[][] integralImage; 
 
    public static void main(String[] args) throws Exception { 
        IntegralImage ii = new IntegralImage(new PixelLoader(new File("C:\\faces\\seed\\false.jpg"))); 
        ii.check(10,10,10,10); 
    } 
 
    public IntegralImage(File image) throws Exception { 
        this(new PixelLoader(image)); 
    } 
 
    public IntegralImage(PixelLoader image) { 
        this.image = image; 
        createIntegralImage(); 
    } 
 
    /** 
     * Allows access to the original PixelLoader object. 
     */ 
    public PixelLoader getPixelLoader() { 
        return image; 
    } 
 
    /** 
     * Simple method to ensure that the integral image is producing the correct output. 
     */ 
    protected boolean check(int x, int y, int width, int height) { 
 
        int sum = 0; 
 
        for (int dy = 0; dy < height; dy++) 
        for (int dx = 0; dx < width; dx++) { 
            sum += image.getGreyValue(x + dx, y + dy); 
        } 
 
        if (getSum(x, y, x + width, y + height) == sum){ 
            System.out.println("Check passed. Both equal=" + sum); 
            return true; 
        } else { 
            System.out.println("Check FAILED"); 
            return false; 
        } 
 
    } 
 
    private void createIntegralImage() { 
 
        final int baseResolutionX = 1; 
        final int baseResolutionY = 1; 
 
        // Prepare an array to store the results in 
        integralImage = new int[image.getWidth() / baseResolutionX + 1][image.getHeight() / baseResolutionY + 1]; 
 
        // The array is at a different position to the image 
        // If the baseResolution is more than 1. A bit messy but 
        // avoids unnecessary multiplications 
        int arrX = 1; 
 
        // Move through each column in the image 
        for (int x = 0; x < image.getWidth(); x += baseResolutionX) { 
 
            int columnTotal = 0; 
            int arrY = 1; 
 
            // Move down the column 
            for (int y = 0; y < image.getHeight(); y += baseResolutionY) { 
 
                // Find the sum of pixels in this column, to this particular Y value 
                // This involves evaluating a square of baseResolution x baseResolution pixels. 
                for (int dx = 0; dx < baseResolutionX; dx++) 
                    for (int dy = 0; dy < baseResolutionY; dy++) 
                        columnTotal += image.getGreyValue(x + dx, y + dy); 
 
                // sum total = value of row to left + columnTotal 
                integralImage[arrX][arrY] = (arrX == 0 ? 0 : integralImage[arrX - 1][arrY]) + columnTotal; 
 
                // results Y index 
                arrY++; 
 
            } 
 
            // results X index 
            arrX++; 
 
        } 
 
    } 
 
    /** 
     * Gets the sum of intensities within a box bounded by two sets of coordinates - (x1,y1), (x2, y2) 
     */ 
    public int getSum(int x1, int y1, int x2, int y2) { 
        int rect1 = integralImage[x1][y1]; 
        int rect2 = integralImage[x2][y1]; 
        int rect3 = integralImage[x1][y2]; 
        int rect4 = integralImage[x2][y2]; 
        return rect4 - rect2 - rect3 + rect1; 
    } 
 
}