OpenCV积分图像统计像素,前面介绍了直方图的计算方法,即遍历图像的全部像素并累计每个强度值在图像中出现的次数。我们也看到,有时只需要计算图像中某个特定区域的直方图。实际上,累计图像某个子区域内的像素总数是很多计算机视觉算法中的常见过程。现在假设需要对图像中的多个感兴趣区域计算几个此类直方图,这些计算过程马上都会变得非常耗时。这种情况下,有一个工具可以极大地提高统计图像子区域像素的效率,那就是积分图像。
使用积分图像统计图像感兴趣区域的像素是一种高效的方法。它在程序中的应用非常广泛,例如用于计算基于不同大小的滑动窗口。
这里的目标是说明如何只用三次算术运算,就能累加一个矩形区域的像素。
如何实现
本文将使用下面的图像来做演示,识别出图像中的一个感兴趣区域,区域内容为一个骑自行车的女孩。
在累加多个图像区域的像素时,积分图像显得非常有用。通常来说,要获得感兴趣区域全部像素的累加和,常规的代码如下所示:
// 打开图像
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);
两种做法得到的结果是一样的。但计算积分图像需要遍历全部像素,因此速度比较慢。关键在于,一旦这个初始计算完成,你只需要添加四个像素就能得到感兴趣区域的累加和,与区域大小无关。因此,如果需要在多个尺寸不同的区域上计算像素累加和,最好采用积分图像。
酷客网相关文章:
评论前必须登录!
注册