积分图像(Integral image)

简介: 积分图算法由Crow在1984年首次提出,是为了在多尺度透视投影中提高渲染速度。积分图算法是一种快速计算图像区域和以及图像区域平方和的算法。它的核心思想就是对每一个图像建立起自己的积分图查找表,在图像处理的阶段就可以根据预先建立积分图查找表直接查找从而实现对均值卷积的线性时间计算。做到了卷积执行的时间与窗口大小无关。之前介绍的NL-means算法就可以采用积分图算法进行优化加速。

从直观来说,一张图像就是一个矩形,这个矩形中每个像素点的积分值,就是以图像左上角像素点为左上角顶点,以该像素点为右下角顶点的矩形中包含的所有元素之和。如下图所示,点(x,y)处的积分值为矩形区域中所有像素之和(包括该点)。

65303aa9ff8e4a02b89bcf64d63a1318.jpg

实际计算积分图的时候,为了提高计算效率,通常不会对每一个像素点都重新计算矩形区域包含的所有元素值之和,而是利用相邻点的积分值实现快速计算,如下图所示,点(x,y)的积分值可以使用点(x-1,y)与点(x,y-1)的积分值之和,然后减去重叠区域,也就是减去点(x-1,y-1)的积分值,最后再加上点(x,y)的像素值得到点(x,y)的积分值。

f946faeb710542369f0042807ffdaf68.jpg

上述原理用公式表示为:

I(x,y) = I(x-1,y) + I(x,y-1) - I(x-1,y-1) + pixel(x,y)

此外还需要考虑边界问题,也就是第一行和第一列的计算。

对于第一行:

I(0,0) = pixel(0,0),x=0,y=0

I(x,0) = I(x-1,0) + pixel(x,0),x>0,y=0

对于第一列:

I(0,y) = I(0,y-1) + pixel(0,y),x=0,y>0


根据上述原理,基于OpenCV与C++的实现代码如下:

voidIntegral(Matsrc, Mat&integal_out)
{  
Mattmp(src.size(), CV_64FC1, 0.0);
tmp.ptr<double>(0)[0] = (double)src.ptr<uchar>(0)[0];
for(inti=1; i<src.cols; i++)   //第一行    {
tmp.ptr<double>(0)[i] =tmp.ptr<double>(0)[i-1] +src.ptr<uchar>(0)[i];
    }
for(inti=1; i<src.rows; i++)  //第一列    {
tmp.ptr<double>(i)[0] =tmp.ptr<double>(i-1)[0] +src.ptr<uchar>(i)[0];
    }
for(inti=1; i<src.rows; i++)   //第i行    {
for(intj=1; j<src.cols; j++)   //第j列       {
tmp.ptr<double>(i)[j] =tmp.ptr<double>(i)[j-1] +tmp.ptr<double>(i-1)[j] -tmp.ptr<double>(i-1)[j-1] +src.ptr<uchar>(i)[j];
        }
    }
tmp.copyTo(integal_out);
}

参考OpenCV的官方文档:

C++: voidintegral(InputArrayimage, OutputArraysum, intsdepth=-1Parameters: 
imageSourceimageasWXH  , 8-bitorfloating-point (32for64f).
sumIntegralimageas (W+1) X (H+1) ,
32-bitintegerorfloating-point (32for64f).
sdepthDesireddepthoftheintegralandthetiltedintegralimages,
CV_32S, CV_32F, orCV_64F.

发现为了能容纳最后一列和最后一行的情况,最终的积分图就应该是 (W + 1) X (H + 1)大小,如下图所示,假设输入图像大小为2x2,则积分图大小为3x3:

80931244fc6546b1be3be4483246bc6a.png

OpenCV官方提供两种积分图函数integral(),可以直接调用:

//API一voidintegral( InputArraysrc,     //输入图像OutputArraysum,    //和表intsdepth=-1,);  //和表深度//API二voidintegral( InputArraysrc,     //输入图像OutputArraysum,    //和表OutputArraysqsum,  //平方和表intsdepth=-1,    //和表深度,一般为CV_32Sintsqdepth=-1 ); //平方和表深度,一般为CV_32F

OpenCV实现过程:

#include <opencv2/opencv.hpp>usingnamespacestd;
usingnamespacecv;
intmain() {
Matsrc, sum, sqrsum;
src=imread("1.png", 0);
integral(src, sum, sqrsum, CV_32S, CV_32F);
normalize(sum, sum, 0, 255, NORM_MINMAX, CV_8UC1, Mat());
normalize(sqrsum, sqrsum, 0, 255, NORM_MINMAX, CV_8UC1, Mat());
imshow("原图", src);
imshow("和表积分图", sum);
imshow("平方和表积分图", sqrsum);
waitKey(0);
return0;
}

我们还可以对兴趣区域(ROI)内的像素求和或者平方和:

#include <opencv2/opencv.hpp>usingnamespacestd;
usingnamespacecv;
intget_block_sum(Mat&sum, intx1, inty1, intx2, inty2);
intmain() {
Matsrc, sum, sqrsum;
src=imread("1.png", 0);
//获取ROI,便于观察(使用ImageWatch插件)intLR=4;
intLC=4;
intwidth=6;
intheight=6;
Matroi=src(Rect(LR, LC, width, height)).clone();   
//计算积分图integral(src, sum, sqrsum, CV_32S, CV_32F);
//利用积分图计算ROI内的像素值总和intvalue=get_block_sum(sum, LR, LC, LR+height, LC+width);
cout<<value<<endl;
imshow("原图", src);        
waitKey(0);
return0;
}
intget_block_sum(Mat&sum, intx1, inty1, intx2, inty2) {
intBottomRight=sum.at<int>(x2, y2);
intTopLeft=sum.at<int>(x1, y1);
intTopRight=sum.at<int>(x1, x2);
intBottomLeft=sum.at<int>(x2, y1);
intsum_value= (BottomRight+TopLeft-TopRight-BottomLeft);
returnsum_value;
}
目录
相关文章
|
计算机视觉 索引
OpenCV-最值计算cv::minMaxIdx&cv::minMaxLoc
OpenCV-最值计算cv::minMaxIdx&cv::minMaxLoc
211 0
|
1月前
|
计算机视觉
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
这篇文章详细介绍了OpenCV库中的图像二值化函数`cv2.threshold`,包括二值化的概念、常见的阈值类型、函数的参数说明以及通过代码实例展示了如何应用该函数进行图像二值化处理,并展示了运行结果。
344 0
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
|
3月前
|
C++
C++ PCL 计算多个RT矩阵变换后的变换矩阵
C++ PCL 计算多个RT矩阵变换后的变换矩阵
49 0
|
5月前
|
资源调度 算法 计算机视觉
【Qt&OpenCV 图像平滑/滤波处理 -- Blur/Gaussian/Median/Bilateral】
【Qt&OpenCV 图像平滑/滤波处理 -- Blur/Gaussian/Median/Bilateral】
68 0
|
5月前
|
算法 Java 计算机视觉
图像处理之双边滤波效果(Bilateral Filtering for Gray and Color Image)
图像处理之双边滤波效果(Bilateral Filtering for Gray and Color Image)
44 0
|
6月前
|
计算机视觉
halcon系列基础之Scale_image_range
halcon系列基础之Scale_image_range
312 0
|
6月前
|
存储 定位技术 计算机视觉
Armadillo与OpenCV矩阵数据mat、vec与Mat的相互转换
Armadillo与OpenCV矩阵数据mat、vec与Mat的相互转换
|
计算机视觉
OpenCV-矩阵归一化cv::normalize
OpenCV-矩阵归一化cv::normalize
|
计算机视觉
OpenCV-离散傅里叶变换cv::dft&cv::idft
OpenCV-离散傅里叶变换cv::dft&cv::idft
150 0
|
存储 编解码 语音技术
swr_get_out_samples和swr_convert,比特率重采样
swr_get_out_samples和swr_convert,比特率重采样
198 0
swr_get_out_samples和swr_convert,比特率重采样