ComputerVision:积分图求解

文章出自:http://yanleilei.com/post/2013-12-04/40060319786   转载请注明出处!

一、概念说明

1、0度积分图求解图示与计算公式

2、-45度积分图求解图示与计算公式


 

3、+45度积分图求解图示与计算公式



二、程序实现

1、C程序代码

  1. //  
  2. //  
  3. // ComputerVision:积分图求解  
  4. //  
  5. // @author Larry  
  6. // @blog http://www.yanleilei.com  
  7. // @date 2013.12.04  
  8. //  
  9.   
  10. #include <cv.h>  
  11. #include <iostream>  
  12. using namespace std;  
  13.   
  14.   
  15.   
  16. void calIntegralImage( IplImage* srcImg, int* intImg );  
  17.   
  18. void calLeft45IntegralImage( IplImage* srcImg, int* intImg );  
  19.   
  20. void calUp45IntegralImage( IplImage* srcImg, int* &intImg );  
  21.   
  22.   
  23.   
  24. void main() {  
  25.     const int WIDTH = 10, HEIGHT = 10;  
  26.     IplImage* img = cvCreateImage( cvSize(WIDTH, HEIGHT), IPL_DEPTH_8U, 1 );  
  27.   
  28.     int count = 0;  
  29.     cout << "SourceImage" << endl;  
  30.     for ( int i = 0; i < HEIGHT; i++ ) { //初始为img赋值  
  31.         for ( int j = 0; j < WIDTH; j++ ) {  
  32.             img->imageData[i*(img->widthStep) + j] = count++;  
  33.             cout << setw(5) << (int)(unsigned char)img->imageData[i*(img->widthStep) + j] << " ";  
  34.         }  
  35.         cout << endl;  
  36.     }  
  37.   
  38.     int* intImg = (int*)malloc(WIDTH * HEIGHT * sizeof(int));  
  39.     int* intLeft45Img = (int*)malloc(WIDTH * HEIGHT * sizeof(int));  
  40.     int* intUp45Img = NULL;  
  41.   
  42.     calIntegralImage( img, intImg );  
  43.     calLeft45IntegralImage( img, intLeft45Img );  
  44.     calUp45IntegralImage( img, intUp45Img );  
  45.   
  46.     cout << "IntegralImage" << endl;  
  47.     for ( int i = 0; i < HEIGHT; i++ ) { //打印0度积分图  
  48.         for ( int j = 0; j < WIDTH; j++ ) {  
  49.             cout << setw(5) << intImg[i*WIDTH + j] << " ";  
  50.         }  
  51.         cout << endl;  
  52.     }  
  53.     cout << endl;  
  54.   
  55.     cout << "Left45IntegralImage" << endl;  
  56.     for ( int i = 0; i < HEIGHT; i++ ) { //打印-45度积分图  
  57.         for ( int j = 0; j < WIDTH; j++ ) {  
  58.             cout << setw(5) << intLeft45Img[i*WIDTH + j] << " ";  
  59.         }  
  60.         cout << endl;  
  61.     }  
  62.     cout << endl;  
  63.   
  64.     cout << "Up45IntegralImage" << endl;  
  65.     for ( int i = 0; i < HEIGHT; i++ ) { //打印+45度积分图  
  66.         for ( int j = 0; j < WIDTH; j++ ) {  
  67.             cout << setw(5) << intUp45Img[i*WIDTH + j] << " ";  
  68.         }  
  69.         cout << endl;  
  70.     }  
  71.     cout << endl;  
  72.   
  73.     //释放内存  
  74.     free( intImg );  
  75.     free( intLeft45Img );  
  76.     free( intUp45Img );  
  77. }  
  78.   
  79.   
  80. /** 
  81.  * 求0度积分图 
  82.  * 
  83.  * @param srcImg 输入 原图 
  84.  * @param intImg 输出 积分图 与原图同样大小 
  85. */  
  86. void calIntegralImage( IplImage* srcImg, int* intImg ) {  
  87.     int i = 0, j = 0;  
  88.     for ( i = 0; i < srcImg->height; i++ ) { //第0列  
  89.         if ( 0 == i ) {  
  90.             intImg[0] = (unsigned char)srcImg->imageData[0];  
  91.         } else {  
  92.             intImg[i*(srcImg->width)] = intImg[(i-1)*(srcImg->width)] + (unsigned char)srcImg->imageData[i*(srcImg->widthStep)];  
  93.         }  
  94.     }  
  95.     for ( j = 0; j < srcImg->width; j++ ) { //第0行  
  96.         if ( 0 == j ) {  
  97.             intImg[0] = (unsigned char)srcImg->imageData[0];  
  98.         } else {  
  99.             intImg[j] = intImg[j-1] + (unsigned char)srcImg->imageData[j];  
  100.         }  
  101.     }  
  102.     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)  
  103.         for ( j = 1; j < srcImg->width; j++ ) {  
  104.             intImg[i*(srcImg->width) + j] =  
  105.                 intImg[i*(srcImg->width) + (j-1)] + intImg[(i-1)*(srcImg->width) + j] -   
  106.                     intImg[(i-1)*(srcImg->width) + (j-1)] + (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + j];  
  107.         }  
  108.     }  
  109. }  
  110.   
  111. /** 
  112.  * 求-45度积分图 
  113.  * 
  114.  * @param srcImg 输入 原图 
  115.  * @param intImg 输出 -45度积分图 与原图同样大小 
  116. */  
  117. void calLeft45IntegralImage( IplImage* srcImg, int* intImg ) {  
  118.     int i = 0, j = 0;  
  119.     int* temp = (int*)malloc((srcImg->width + 1) * (srcImg->height) * sizeof(int));//创建 (宽+1)*高 临时数组  
  120.     for ( i = 0; i < srcImg->height; i++ ) { //第0列补0,第1列是原图第0列   
  121.         temp[i*(srcImg->width + 1)] = 0;  
  122.         temp[i*(srcImg->width + 1) + 1] = (unsigned char)srcImg->imageData[i*(srcImg->widthStep)];  
  123.     }  
  124.     for ( j = 2; j < srcImg->width + 1; j++ ) { //从第2列开始 按列赋值  
  125.         for ( i = 0; i < srcImg->height; i++ ) {  
  126.             if ( 0 == i ) { //该列首元素 RSAT(x,y)=RSAT(x-1,y+1)+I(x-1,y)+I(x,y)  
  127.                 temp[i*(srcImg->width + 1) + j] = temp[(i+1)*(srcImg->width + 1) + (j-1)] +  
  128.                     (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-2)] +  
  129.                         (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-1)];  
  130.             } else if ( i == srcImg->height - 1 ) { //该列尾元素 RSAT(x,y)=RSAT(x-1,y-1)+I(x-1,y)+I(x,y)  
  131.                 temp[i*(srcImg->width + 1) + j] = temp[(i-1)*(srcImg->width + 1) + (j-1)] +  
  132.                     (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-2)] +  
  133.                         (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-1)];  
  134.             } 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)  
  135.                 temp[i*(srcImg->width + 1) + j] =  
  136.                     temp[(i-1)*(srcImg->width + 1) + (j-1)] + temp[(i+1)*(srcImg->width + 1) + (j-1)] -   
  137.                         temp[i*(srcImg->width + 1) + (j-2)] + (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-2)] +  
  138.                             (unsigned char)srcImg->imageData[i*(srcImg->widthStep) + (j-1)];  
  139.             }  
  140.         }  
  141.     }  
  142.   
  143.     for ( i = 0; i < srcImg->height; i++ ) { //复制temp数组除第0列以外的所有列给intImg数组  即为所求  
  144.         for ( j = 0; j < srcImg->width; j++ ) {  
  145.             intImg[i*srcImg->width + j] = temp[i*(srcImg->width + 1) + (j+1)];  
  146.         }  
  147.     }  
  148.     free( temp ); //释放临时空间  
  149. }  
  150.   
  151.   
  152. /** 
  153.  * 求+45度积分图 
  154.  * 
  155.  * @param srcImg 输入 原图 
  156.  * @param intImg 输出 +45度积分图 与原图同样大小 注意初始不用为intImg申请空间 
  157. */  
  158. void calUp45IntegralImage( IplImage* srcImg, int* &intImg ) { //特别注意 第二个参数传的是指针本身  并不是副本  
  159.     int i = 0, j = 0;  
  160.     int* temp = (int*)malloc((srcImg->width) * (srcImg->height + 1) * sizeof(int));//创建 宽*(高+1) 临时数组  
  161.     for ( j = 0; j < srcImg->width; j++ ) { //第0行补0, 第1行为原图第0行  
  162.         temp[j] = 0;  
  163.         temp[srcImg->width + j] = (unsigned char)srcImg->imageData[j];  
  164.     }  
  165.     for ( i = 2; i < srcImg->height + 1; i++ ) { //从第2行开始 按行赋值  
  166.         for ( j = 0; j < srcImg->width; j++ ) {  
  167.             if ( 0 == j ) { //该行首元素 RSAT(x,y)=RSAT(x+1,y-1)+I(x,y-1)+I(x,y)  
  168.                 temp[i*(srcImg->width) + j] = temp[(i-1)*(srcImg->width) + (j+1)] +   
  169.                     (unsigned char)srcImg->imageData[(i-2)*(srcImg->widthStep) + j] +   
  170.                         (unsigned char)srcImg->imageData[(i-1)*(srcImg->widthStep) + j];  
  171.             } else if ( j == srcImg->width - 1 ) { //该行尾元素 RSAT(x,y)=RSAT(x-1,y-1)+I(x,y-1)+I(x,y)  
  172.                 temp[i*(srcImg->width) + j] = temp[(i-1)*(srcImg->width) + (j-1)] +   
  173.                     (unsigned char)srcImg->imageData[(i-2)*(srcImg->widthStep) + j] +   
  174.                         (unsigned char)srcImg->imageData[(i-1)*(srcImg->widthStep) + j];  
  175.             } 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)  
  176.                 temp[i*(srcImg->width) + j] = temp[(i-1)*(srcImg->width) + (j-1)] +   
  177.                     temp[(i-1)*(srcImg->width) + (j+1)] - temp[(i-2)*(srcImg->width) + j] +   
  178.                             (unsigned char)srcImg->imageData[(i-2)*(srcImg->widthStep) + j] +  
  179.                                 (unsigned char)srcImg->imageData[(i-1)*(srcImg->widthStep) + j];  
  180.             }  
  181.         }  
  182.     }  
  183.     intImg = temp + srcImg->width; //不要第0行 intImg指针起点 指向第1行首元素 即为所求  
  184. }  
//
//
// 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、执行结果



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值