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;
}
}