// Catalano Imaging Library
// The Catalano Framework
//
// Copyright © Diego Catalano, 2012-2016
// diego.catalano at live.com
//
// Copyright © Andrew Kirillov, 2007-2013
// andrew.kirillov at gmail.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
package Catalano.Imaging.Tools;
import Catalano.Imaging.FastBitmap;
/**
* Integral Image.
*
The class implements integral image concept, which is described by Viola and Jones in: P. Viola and M. J. Jones, "Robust real-time face detection", Int. Journal of Computer Vision 57(2), pp. 137–154, 2004.
* An integral image I of an input image G is defined as the image in which the intensity at a pixel position is equal to the sum of the intensities of all the pixels above and to the left of that position in the original image.
* @author Diego Catalano
*/
public class IntegralImage {
/**
* Provides access to internal array keeping integral image data.
*/
protected int[][] integralImage = null;
private int width;
private int height;
/**
* Initializes a new instance of the IntegralImage class.
* @param fastBitmap An image to be processed.
*/
public IntegralImage(FastBitmap fastBitmap) {
this(fastBitmap, 1);
}
/**
* Initializes a new instance of the IntegralImage class.
* @param fastBitmap An image to be processed.
* @param power Power of the number.
*/
public IntegralImage(FastBitmap fastBitmap, int power) {
this.width = fastBitmap.getWidth();
this.height = fastBitmap.getHeight();
Process(fastBitmap, power);
}
/**
* Initializes a new instance of the IntegralImage class.
* @param width Image width.
* @param height Image height.
*/
protected IntegralImage(int width, int height){
this.width = width;
this.height = height;
this.integralImage = new int[height + 1][width + 1];
}
/**
* Width of the source image the integral image was constructed for.
* @return Width.
*/
public int getWidth() {
return width;
}
/**
* Height of the source image the integral image was constructed for.
* @return Height.
*/
public int getHeight() {
return height;
}
/**
* Provides access to internal array keeping integral image data.
* @return Data.
*/
public int[][] getInternalData(){
return integralImage;
}
/**
* Provides access to internal value keeping integral image data.
* @param x X axis coordinate.
* @param y Y axis coordinate.
* @return Integral value.
*/
public int getInternalData(int x, int y){
return integralImage[x][y];
}
/**
* Construct integral image from source grayscale image.
* @param fastBitmap Image to be processed.
* @return Returns integral image.
*/
public static IntegralImage FromFastBitmap(FastBitmap fastBitmap){
return FromFastBitmap(fastBitmap, 1);
}
/**
* Construct integral image from source grayscale image.
* @param fastBitmap Image to be processed.
* @param power Power of the number.
* @return Returns integral image.
*/
public static IntegralImage FromFastBitmap(FastBitmap fastBitmap, int power){
// get source image size
int width = fastBitmap.getWidth();
int height = fastBitmap.getHeight();
// create integral image
IntegralImage im = new IntegralImage( width, height );
int[][] integralImage = im.integralImage;
for (int i = 1; i <= height; i++) {
int rowSum = 0;
for (int j = 1; j <= width; j++) {
rowSum += Math.pow(fastBitmap.getGray(i - 1, j - 1), power);
integralImage[i][j] = rowSum + integralImage[i - 1][j];
}
}
return im;
}
/**
* Process image.
* @param fastBitmap Image to be processed.
*/
private void Process(FastBitmap fastBitmap, int power){
if (!fastBitmap.isGrayscale()) {
try {
throw new Exception("IntegralImage works only with Grayscale images");
} catch (Exception e) {
e.printStackTrace();
}
}
integralImage = new int[height + 1][width + 1];
for (int x = 1; x < height + 1; x++) {
int rowSum = 0;
for (int y = 1; y < width + 1; y++) {
rowSum += Math.pow(fastBitmap.getGray(x - 1, y - 1), power);
integralImage[x][y] = rowSum + integralImage[x - 1][y];
}
}
}
/**
* Calculate sum of pixels in the specified rectangle.
* @param x1 Coordinate of left-top rectangle's corner.
* @param y1 Coordinate of left-top rectangle's corner.
* @param x2 Coordinate of right-bottom rectangle's corner.
* @param y2 Coordinate of right-bottom rectangle's corner.
* @return Returns sum of pixels in the specified rectangle.
*/
public int getRectangleSum(int x1, int y1, int x2, int y2){
// check if requested rectangle is out of the image
if ( ( x2 < 0 ) || ( y2 < 0 ) || ( x1 >= height ) || ( y1 >= width ) )
return 0;
if ( x1 < 0 ) x1 = 0;
if ( y1 < 0 ) y1 = 0;
x2++;
y2++;
if ( x2 > height ) x2 = height;
if ( y2 > width ) y2 = width;
return integralImage[x2][y2] + integralImage[x1][y1] - integralImage[x1][y2] - integralImage[x2][y2];
}
/**
* Calculate sum of pixels in the specified rectangle.
* @param x Coordinate of central point of the rectangle.
* @param y Coordinate of central point of the rectangle.
* @param radius Radius of the rectangle.
* @return Returns sum of pixels in the specified rectangle.
*/
public int getRectangleSum(int x, int y, int radius){
return getRectangleSum(x - radius, y - radius, x + radius, y + radius);
}
/**
* Calculate horizontal (X) haar wavelet at the specified point.
* @param x X coordinate of the point to calculate wavelet at.
* @param y Y coordinate of the point to calculate wavelet at.
* @param radius Wavelet size to calculate.
* @return Returns value of the horizontal wavelet at the specified point.
*/
public int getHarrXWavelet(int x, int y, int radius){
int y1 = y - radius;
int y2 = y + radius - 1;
int a = getRectangleSum( x, y1, x + radius - 1, y2 );
int b = getRectangleSum( x - radius, y1, x - 1, y2 );
return (int) ( a - b );
}
/**
* Calculate vertical (Y) haar wavelet at the specified point.
* @param x X coordinate of the point to calculate wavelet at.
* @param y Y coordinate of the point to calculate wavelet at.
* @param radius Wavelet size to calculate.
* @return Returns value of the vertical wavelet at the specified point.
*/
public int getHaarYWavelet( int x, int y, int radius ){
int x1 = x - radius;
int x2 = x + radius - 1;
float a = getRectangleSum( x1, y, x2, y + radius - 1 );
float b = getRectangleSum( x1, y - radius, x2, y - 1 );
return (int) ( a - b );
}
/**
* Calculate mean value of pixels in the specified rectangle.
* @param x1 X coordinate of left-top rectangle's corner.
* @param y1 Y coordinate of left-top rectangle's corner.
* @param x2 X coordinate of right-bottom rectangle's corner.
* @param y2 Y coordinate of right-bottom rectangle's corner.
* @return Returns mean value of pixels in the specified rectangle.
*/
public float getRectangleMean(int x1, int y1, int x2, int y2){
// check if requested rectangle is out of the image
if ( ( x2 < 0 ) || ( y2 < 0 ) || ( x1 >= height ) || ( y1 >= width ) )
return 0;
if ( x1 < 0 ) x1 = 0;
if ( y1 < 0 ) y1 = 0;
x2++;
y2++;
if ( x2 > height ) x2 = height;
if ( y2 > width ) y2 = width;
// return sum divided by actual rectangles size
return (float) ( (double) ( integralImage[x2][y2] + integralImage[x1][y1] - integralImage[x1][y2] - integralImage[x2][y1] ) /
(double) ( ( x2 - x1 ) * ( y2 - y1 ) ) );
}
/**
* Calculate mean value of pixels in the specified rectangle.
* @param x X coordinate of central point of the rectangle.
* @param y Y coordinate of central point of the rectangle.
* @param radius Radius of the rectangle.
* @return Returns mean value of pixels in the specified rectangle.
*/
public float getRectangleMean(int x, int y, int radius){
return getRectangleMean(x - radius, y - radius, x + radius, y + radius);
}
/**
* Calculate mean value of pixels in the specified rectangle without checking it's coordinates.
* @param x1 X coordinate of left-top rectangle's corner.
* @param y1 Y coordinate of left-top rectangle's corner.
* @param x2 X coordinate of right-bottom rectangle's corner.
* @param y2 Y coordinate of right-bottom rectangle's corner.
* @return Returns mean value of pixels in the specified rectangle.
*/
public int getRectangleSumUnsafe( int x1, int y1, int x2, int y2 ){
x2++;
y2++;
return integralImage[x2][y2] + integralImage[x1][y1] - integralImage[x2][y1] - integralImage[x1][y2];
}
/**
* Calculate sum of pixels in the specified rectangle without checking it's coordinates.
* @param x X coordinate of central point of the rectangle.
* @param y Y coordinate of central point of the rectangle.
* @param radius Radius of the rectangle.
* @return Returns sum of pixels in the specified rectangle.
*/
public int getRectangleSumUnsafe( int x, int y, int radius ){
return getRectangleSumUnsafe( x - radius, y - radius, x + radius, y + radius );
}
/**
* Calculate mean value of pixels in the specified rectangle without checking it's coordinates.
* @param x1 X coordinate of left-top rectangle's corner.
* @param y1 Y coordinate of left-top rectangle's corner.
* @param x2 X coordinate of right-bottom rectangle's corner.
* @param y2 Y coordinate of right-bottom rectangle's corner.
* @return Returns mean value of pixels in the specified rectangle.
*/
public float getRectangleMeanUnsafe( int x1, int y1, int x2, int y2 ){
x2++;
y2++;
// return sum divided by actual rectangles size
return (float) ( (double) ( integralImage[x2][y2] + integralImage[x1][y1] - integralImage[x1][y2] - integralImage[x2][y1] ) /
(double) ( ( x2 - x1 ) * ( y2 - y1 ) ) );
}
/**
* Calculate mean value of pixels in the specified rectangle without checking it's coordinates.
* @param x X coordinate of central point of the rectangle.
* @param y Y coordinate of central point of the rectangle.
* @param radius Radius of the rectangle.
* @return Returns mean value of pixels in the specified rectangle.
*/
public float getRectangleMeanUnsafe( int x, int y, int radius ){
return getRectangleMeanUnsafe( x - radius, y - radius, x + radius, y + radius );
}
}
Ads help maintain this website.