文章出自:http://yanleilei.com/post/2013-12-04/40060319786 转载请注明出处!
一、概念说明
1、0度积分图求解图示与计算公式2、-45度积分图求解图示与计算公式
3、+45度积分图求解图示与计算公式
二、程序实现
1、C程序代码
- //
- //
- // ComputerVision:积分图求解
- //
- // @author Larry
- // @blog http://www.yanleilei.com
- // @date 2013.12.04
- //
- #include <cv.h>
- #include <iostream>
- using namespace std;
- void calIntegralImage( IplImage* srcImg, int* intImg );
- void calLeft45IntegralImage( IplImage* srcImg, int* intImg );
- void calUp45IntegralImage( IplImage* srcImg, int* &intImg );
- void main() {
- const int WIDTH = 10, HEIGHT = 10;
- IplImage* img = cvCreateImage( cvSize(WIDTH, HEIGHT), IPL_DEPTH_8U, 1 );
- int count = 0;
- cout << "SourceImage" << endl;
- for ( int i = 0; i < HEIGHT; i++ ) { //初始为img赋值
- for ( int j = 0; j < WIDTH; j++ ) {
- img->imageData[i*(img->widthStep) + j] = count++;
- cout << setw(5) << (int)(unsigned char)img->imageData[i*(img->widthStep) + j] << " ";
- }
- cout << endl;
- }
- int* intImg = (int*)malloc(WIDTH * HEIGHT * sizeof(int));
- int* intLeft45Img = (int*)malloc(WIDTH * HEIGHT * sizeof(int));
- int* intUp45Img = NULL;
- calIntegralImage( img, intImg );
- calLeft45IntegralImage( img, intLeft45Img );
- calUp45IntegralImage( img, intUp45Img );
- cout << "IntegralImage" << endl;
- for ( int i = 0; i < HEIGHT; i++ ) { //打印0度积分图
- for ( int j = 0; j < WIDTH; j++ ) {
- cout << setw(5) << intImg[i*WIDTH + j] << " ";
- }
- cout << endl;
- }
- cout << endl;
- cout << "Left45IntegralImage" << endl;
- for ( int i = 0; i < HEIGHT; i++ ) { //打印-45度积分图
- for ( int j = 0; j < WIDTH; j++ ) {
- cout << setw(5) << intLeft45Img[i*WIDTH + j] << " ";
- }
- cout << endl;
- }
- cout << endl;
- cout << "Up45IntegralImage" << endl;
- for ( int i = 0; i < HEIGHT; i++ ) { //打印+45度积分图
- for ( int j = 0; j < WIDTH; j++ ) {
- cout << setw(5) << intUp45Img[i*WIDTH + j] << " ";
- }
- cout << endl;
- }
- cout << endl;
- //释放内存
- free( intImg );
- free( intLeft45Img );
- free( intUp45Img );
- }
- /**
- * 求0度积分图
- *
- * @param srcImg 输入 原图
- * @param intImg 输出 积分图 与原图同样大小
- */
- void calIntegralImage( IplImage* srcImg, int* intImg ) {
- int i = 0, j = 0;
- for ( i = 0; i < srcImg->height; i++ ) { //第0列
- if ( 0 == i ) {
- intImg[0] = (unsigned char)srcImg->imageData[0];
- } else {
- intImg[i*(srcImg->width)] = intImg[(i-1)*(srcImg->width)] + (unsigned char)srcImg->imageData[i*(srcImg->widthStep)];
- }
- }
- for ( j = 0; j < srcImg->width; j++ ) { //第0行
- if ( 0 == j ) {
- intImg[0] = (unsigned char)srcImg->imageData[0];
- } else {
- intImg[j] = intImg[j-1] + (unsigned char)srcImg->imageData[j];
- }
- }
- for ( i = 1; i < srcImg->height; i++ ) { //一般情况 SAT(x,y)=SAT(x-1,y)+SAT(x,y-1)-SAT(x-1,y-1)+I(x,y)
- for ( j = 1; j < srcImg->width; j++ ) {
- intImg[i*(srcImg->width) + j] =
- intImg[i*(srcImg->width) + (j-1)] + intImg[(i-1)*(srcImg->width) + j] -
- intImg[(i-1)*(srcImg->width) + (j-1)] + (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + j];
- }
- }
- }
- /**
- * 求-45度积分图
- *
- * @param srcImg 输入 原图
- * @param intImg 输出 -45度积分图 与原图同样大小
- */
- void calLeft45IntegralImage( IplImage* srcImg, int* intImg ) {
- int i = 0, j = 0;
- int* temp = (int*)malloc((srcImg->width + 1) * (srcImg->height) * sizeof(int));//创建 (宽+1)*高 临时数组
- for ( i = 0; i < srcImg->height; i++ ) { //第0列补0,第1列是原图第0列
- temp[i*(srcImg->width + 1)] = 0;
- temp[i*(srcImg->width + 1) + 1] = (unsigned char)srcImg->imageData[i*(srcImg->widthStep)];
- }
- for ( j = 2; j < srcImg->width + 1; j++ ) { //从第2列开始 按列赋值
- for ( i = 0; i < srcImg->height; i++ ) {
- if ( 0 == i ) { //该列首元素 RSAT(x,y)=RSAT(x-1,y+1)+I(x-1,y)+I(x,y)
- temp[i*(srcImg->width + 1) + j] = temp[(i+1)*(srcImg->width + 1) + (j-1)] +
- (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-2)] +
- (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-1)];
- } else if ( i == srcImg->height - 1 ) { //该列尾元素 RSAT(x,y)=RSAT(x-1,y-1)+I(x-1,y)+I(x,y)
- temp[i*(srcImg->width + 1) + j] = temp[(i-1)*(srcImg->width + 1) + (j-1)] +
- (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-2)] +
- (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-1)];
- } else { //该列中间元素 采用一般公式 RSAT(x,y)=RSAT(x-1,y-1)+RSAT(x-1,y+1)-RSAT(x-2,y)+I(x-1,y)+I(x,y)
- temp[i*(srcImg->width + 1) + j] =
- temp[(i-1)*(srcImg->width + 1) + (j-1)] + temp[(i+1)*(srcImg->width + 1) + (j-1)] -
- temp[i*(srcImg->width + 1) + (j-2)] + (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-2)] +
- (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-1)];
- }
- }
- }
- for ( i = 0; i < srcImg->height; i++ ) { //复制temp数组除第0列以外的所有列给intImg数组 即为所求
- for ( j = 0; j < srcImg->width; j++ ) {
- intImg[i*srcImg->width + j] = temp[i*(srcImg->width + 1) + (j+1)];
- }
- }
- free( temp ); //释放临时空间
- }
- /**
- * 求+45度积分图
- *
- * @param srcImg 输入 原图
- * @param intImg 输出 +45度积分图 与原图同样大小 注意初始不用为intImg申请空间
- */
- void calUp45IntegralImage( IplImage* srcImg, int* &intImg ) { //特别注意 第二个参数传的是指针本身 并不是副本
- int i = 0, j = 0;
- int* temp = (int*)malloc((srcImg->width) * (srcImg->height + 1) * sizeof(int));//创建 宽*(高+1) 临时数组
- for ( j = 0; j < srcImg->width; j++ ) { //第0行补0, 第1行为原图第0行
- temp[j] = 0;
- temp[srcImg->width + j] = (unsigned char)srcImg->imageData[j];
- }
- for ( i = 2; i < srcImg->height + 1; i++ ) { //从第2行开始 按行赋值
- for ( j = 0; j < srcImg->width; j++ ) {
- if ( 0 == j ) { //该行首元素 RSAT(x,y)=RSAT(x+1,y-1)+I(x,y-1)+I(x,y)
- temp[i*(srcImg->width) + j] = temp[(i-1)*(srcImg->width) + (j+1)] +
- (unsigned char)srcImg->imageData[(i-2)*(srcImg->widthStep) + j] +
- (unsigned char)srcImg->imageData[(i-1)*(srcImg->widthStep) + j];
- } else if ( j == srcImg->width - 1 ) { //该行尾元素 RSAT(x,y)=RSAT(x-1,y-1)+I(x,y-1)+I(x,y)
- temp[i*(srcImg->width) + j] = temp[(i-1)*(srcImg->width) + (j-1)] +
- (unsigned char)srcImg->imageData[(i-2)*(srcImg->widthStep) + j] +
- (unsigned char)srcImg->imageData[(i-1)*(srcImg->widthStep) + j];
- } else { //该行中间元素 采用一般公式 RSAT(x,y)=RSAT(x-1,y-1)+RSAT(x+1,y-1)-RSAT(x,y-2)+I(x,y-1)+I(x,y)
- temp[i*(srcImg->width) + j] = temp[(i-1)*(srcImg->width) + (j-1)] +
- temp[(i-1)*(srcImg->width) + (j+1)] - temp[(i-2)*(srcImg->width) + j] +
- (unsigned char)srcImg->imageData[(i-2)*(srcImg->widthStep) + j] +
- (unsigned char)srcImg->imageData[(i-1)*(srcImg->widthStep) + j];
- }
- }
- }
- intImg = temp + srcImg->width; //不要第0行 intImg指针起点 指向第1行首元素 即为所求
- }
//
//
// ComputerVision:积分图求解
//
// @author Larry
// @blog http://www.yanleilei.com
// @date 2013.12.04
//
#include <cv.h>
#include <iostream>
using namespace std;
void calIntegralImage( IplImage* srcImg, int* intImg );
void calLeft45IntegralImage( IplImage* srcImg, int* intImg );
void calUp45IntegralImage( IplImage* srcImg, int* &intImg );
void main() {
const int WIDTH = 10, HEIGHT = 10;
IplImage* img = cvCreateImage( cvSize(WIDTH, HEIGHT), IPL_DEPTH_8U, 1 );
int count = 0;
cout << "SourceImage" << endl;
for ( int i = 0; i < HEIGHT; i++ ) { //初始为img赋值
for ( int j = 0; j < WIDTH; j++ ) {
img->imageData[i*(img->widthStep) + j] = count++;
cout << setw(5) << (int)(unsigned char)img->imageData[i*(img->widthStep) + j] << " ";
}
cout << endl;
}
int* intImg = (int*)malloc(WIDTH * HEIGHT * sizeof(int));
int* intLeft45Img = (int*)malloc(WIDTH * HEIGHT * sizeof(int));
int* intUp45Img = NULL;
calIntegralImage( img, intImg );
calLeft45IntegralImage( img, intLeft45Img );
calUp45IntegralImage( img, intUp45Img );
cout << "IntegralImage" << endl;
for ( int i = 0; i < HEIGHT; i++ ) { //打印0度积分图
for ( int j = 0; j < WIDTH; j++ ) {
cout << setw(5) << intImg[i*WIDTH + j] << " ";
}
cout << endl;
}
cout << endl;
cout << "Left45IntegralImage" << endl;
for ( int i = 0; i < HEIGHT; i++ ) { //打印-45度积分图
for ( int j = 0; j < WIDTH; j++ ) {
cout << setw(5) << intLeft45Img[i*WIDTH + j] << " ";
}
cout << endl;
}
cout << endl;
cout << "Up45IntegralImage" << endl;
for ( int i = 0; i < HEIGHT; i++ ) { //打印+45度积分图
for ( int j = 0; j < WIDTH; j++ ) {
cout << setw(5) << intUp45Img[i*WIDTH + j] << " ";
}
cout << endl;
}
cout << endl;
//释放内存
free( intImg );
free( intLeft45Img );
free( intUp45Img );
}
/**
* 求0度积分图
*
* @param srcImg 输入 原图
* @param intImg 输出 积分图 与原图同样大小
*/
void calIntegralImage( IplImage* srcImg, int* intImg ) {
int i = 0, j = 0;
for ( i = 0; i < srcImg->height; i++ ) { //第0列
if ( 0 == i ) {
intImg[0] = (unsigned char)srcImg->imageData[0];
} else {
intImg[i*(srcImg->width)] = intImg[(i-1)*(srcImg->width)] + (unsigned char)srcImg->imageData[i*(srcImg->widthStep)];
}
}
for ( j = 0; j < srcImg->width; j++ ) { //第0行
if ( 0 == j ) {
intImg[0] = (unsigned char)srcImg->imageData[0];
} else {
intImg[j] = intImg[j-1] + (unsigned char)srcImg->imageData[j];
}
}
for ( i = 1; i < srcImg->height; i++ ) { //一般情况 SAT(x,y)=SAT(x-1,y)+SAT(x,y-1)-SAT(x-1,y-1)+I(x,y)
for ( j = 1; j < srcImg->width; j++ ) {
intImg[i*(srcImg->width) + j] =
intImg[i*(srcImg->width) + (j-1)] + intImg[(i-1)*(srcImg->width) + j] -
intImg[(i-1)*(srcImg->width) + (j-1)] + (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + j];
}
}
}
/**
* 求-45度积分图
*
* @param srcImg 输入 原图
* @param intImg 输出 -45度积分图 与原图同样大小
*/
void calLeft45IntegralImage( IplImage* srcImg, int* intImg ) {
int i = 0, j = 0;
int* temp = (int*)malloc((srcImg->width + 1) * (srcImg->height) * sizeof(int));//创建 (宽+1)*高 临时数组
for ( i = 0; i < srcImg->height; i++ ) { //第0列补0,第1列是原图第0列
temp[i*(srcImg->width + 1)] = 0;
temp[i*(srcImg->width + 1) + 1] = (unsigned char)srcImg->imageData[i*(srcImg->widthStep)];
}
for ( j = 2; j < srcImg->width + 1; j++ ) { //从第2列开始 按列赋值
for ( i = 0; i < srcImg->height; i++ ) {
if ( 0 == i ) { //该列首元素 RSAT(x,y)=RSAT(x-1,y+1)+I(x-1,y)+I(x,y)
temp[i*(srcImg->width + 1) + j] = temp[(i+1)*(srcImg->width + 1) + (j-1)] +
(unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-2)] +
(unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-1)];
} else if ( i == srcImg->height - 1 ) { //该列尾元素 RSAT(x,y)=RSAT(x-1,y-1)+I(x-1,y)+I(x,y)
temp[i*(srcImg->width + 1) + j] = temp[(i-1)*(srcImg->width + 1) + (j-1)] +
(unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-2)] +
(unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-1)];
} else { //该列中间元素 采用一般公式 RSAT(x,y)=RSAT(x-1,y-1)+RSAT(x-1,y+1)-RSAT(x-2,y)+I(x-1,y)+I(x,y)
temp[i*(srcImg->width + 1) + j] =
temp[(i-1)*(srcImg->width + 1) + (j-1)] + temp[(i+1)*(srcImg->width + 1) + (j-1)] -
temp[i*(srcImg->width + 1) + (j-2)] + (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-2)] +
(unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-1)];
}
}
}
for ( i = 0; i < srcImg->height; i++ ) { //复制temp数组除第0列以外的所有列给intImg数组 即为所求
for ( j = 0; j < srcImg->width; j++ ) {
intImg[i*srcImg->width + j] = temp[i*(srcImg->width + 1) + (j+1)];
}
}
free( temp ); //释放临时空间
}
/**
* 求+45度积分图
*
* @param srcImg 输入 原图
* @param intImg 输出 +45度积分图 与原图同样大小 注意初始不用为intImg申请空间
*/
void calUp45IntegralImage( IplImage* srcImg, int* &intImg ) { //特别注意 第二个参数传的是指针本身 并不是副本
int i = 0, j = 0;
int* temp = (int*)malloc((srcImg->width) * (srcImg->height + 1) * sizeof(int));//创建 宽*(高+1) 临时数组
for ( j = 0; j < srcImg->width; j++ ) { //第0行补0, 第1行为原图第0行
temp[j] = 0;
temp[srcImg->width + j] = (unsigned char)srcImg->imageData[j];
}
for ( i = 2; i < srcImg->height + 1; i++ ) { //从第2行开始 按行赋值
for ( j = 0; j < srcImg->width; j++ ) {
if ( 0 == j ) { //该行首元素 RSAT(x,y)=RSAT(x+1,y-1)+I(x,y-1)+I(x,y)
temp[i*(srcImg->width) + j] = temp[(i-1)*(srcImg->width) + (j+1)] +
(unsigned char)srcImg->imageData[(i-2)*(srcImg->widthStep) + j] +
(unsigned char)srcImg->imageData[(i-1)*(srcImg->widthStep) + j];
} else if ( j == srcImg->width - 1 ) { //该行尾元素 RSAT(x,y)=RSAT(x-1,y-1)+I(x,y-1)+I(x,y)
temp[i*(srcImg->width) + j] = temp[(i-1)*(srcImg->width) + (j-1)] +
(unsigned char)srcImg->imageData[(i-2)*(srcImg->widthStep) + j] +
(unsigned char)srcImg->imageData[(i-1)*(srcImg->widthStep) + j];
} else { //该行中间元素 采用一般公式 RSAT(x,y)=RSAT(x-1,y-1)+RSAT(x+1,y-1)-RSAT(x,y-2)+I(x,y-1)+I(x,y)
temp[i*(srcImg->width) + j] = temp[(i-1)*(srcImg->width) + (j-1)] +
temp[(i-1)*(srcImg->width) + (j+1)] - temp[(i-2)*(srcImg->width) + j] +
(unsigned char)srcImg->imageData[(i-2)*(srcImg->widthStep) + j] +
(unsigned char)srcImg->imageData[(i-1)*(srcImg->widthStep) + j];
}
}
}
intImg = temp + srcImg->width; //不要第0行 intImg指针起点 指向第1行首元素 即为所求
}
2、执行结果