AIHIA梦工厂
标题:
CV系列之利用积分图像统计ROI的像素
[打印本页]
作者:
dongguazi
时间:
2023-8-27 09:08 PM
标题:
CV系列之利用积分图像统计ROI的像素
1.分析
直方图的计算方法,即遍历图像的全部像素并累计每个强度值在图像中出现的次数。我们也看到,有时只需要计算图像中某个特定区域的直方图。实际上,累计图像某个子区 域内的像素总数是很多计算机视觉算法中的常见过程。现在假设需要对图像中的多个感兴趣区域计算几个此类直方图,这些计算过程马上都会变得非常耗时。这种情况下,有一个工具可以极大地提高统计图像子区域像素的效率,那就是积分图像。 使用积分图像统计图像感兴趣区域的像素是一种高效的方法。它在程序中的应用非常广泛, 例如用于计算基于不同大小的滑动窗口。 本节将讲解积分图像背后的原理。这里的目标是说明如何只用三次算术运算,就能累加一个矩形区域的像素。
在累加多个图像区域的像素时,积分图像显得非常有用。通常来说,要获得感兴趣区域全部 像素的累加和,常规的代码如下所示:
// 打开图像
cv::Mat image= cv::imread("bike55.bmp",0);
// 定义图像的 ROI(这里为骑自行车的女孩)
int xo=97, yo=112; int width=25, height=30;
cv::Mat roi(image,cv::Rect(xo,yo,width,height));
// 计算累加值 // 返回一个多通道图像下的 Scalar 数值
cv::Scalar sum= cv::sum(roi);
cv::sum 函数只是遍历区域内的所有像素,并计算累加和。使用积分图像后,只需要三次 加法运算即可实现该功能。不过你得先计算积分图像,代码如下所示:
// 计算积分图像 cv::Mat integralImage;
cv::integral(image,integralImage,CV_32S);
可以在积分图像上用简单的算术表达式获得同样的结果(下一节会详细解释),代码为:
// 用三个加/减运算得到一个区域的累加值
int sumInt= integralImage.at<int>(yo+height,xo+width)– integralImage.at<int>(yo+height,xo)– integralImage.at<int>(yo,xo+width)+ integralImage.at<int>(yo,xo);
两种做法得到的结果是一样的。但计算积分图像需要遍历全部像素,因此速度比较慢。关键在于,一旦这个初始计算完成,你只需要添加四个像素就能得到感兴趣区域的累加和,与区域大小无关。 因此,如果需要在多个尺寸不同的区域上计算像素累加和,最好采用积分图像。
2.解析:
目标就是计算出ROI区域D的面积。
我们通过ROI矩形坐标将x0+w,y0+h划分为ABCD四个区域,每个点对应的数值就是之前图像所有点的积分数值,因此通过数学公式可以求出D的面积。
对于
面积
D=S(x0+w,y0+h)-S(x0,y0+h)-S(x0+w,y0)+S(x0,y0)
=(SA+SB+SC+SD)-(SA+SB+SC)-(SA+SB)+(SA)=SD
通过以上的操作,非常容易就求出了ROI的像素。
3. 总结:
取图像左上方的全部像素计算累加和,并用这个累加和替换图像中的每一个像素,用这种方式得到的图像称为积分图像。计算积分图像时,只需对图像扫描一次。实际上,当前像素的积分值等 于上方像素的积分值加上当前行的累计值。因此积分图像就是一个包含像素累加和的新图像。为 防止溢出,积分图像的值通常采用 int 类型(CV_32S)或 float 类型(CV_32F)。
参考来源于:OpenCV计算机视觉编程攻略
欢迎光临 AIHIA梦工厂 (https://aihiamgc.com/)
Powered by Discuz! X3.5