OpenCV中积分图函数与应用
一:图像积分图概念
积分图像是Crow在1984年首次提出,是为了在多尺度透视投影中提高渲染速度。随后这种技术被应用到基于NCC的快速匹配、对象检测和SURF变换中、基于统计学的快速滤波器等方面。积分图像是一种在图像中快速计算矩形区域和的方法,这种算法主要优点是一旦积分图像首先被计算出来我们可以计算图像中任意大小矩形区域的和而且是在常量时间内。这样在图像模糊、边缘提取、对象检测的时候极大降低计算量、提高计算速度。第一个应用积分图像技术的应用是在Viola-Jones的对象检测框架中出现。


上图左侧四个点的矩形区域像素求和,只要根据每个点左上方所有像素和表值,进行两次减法与一次加法即可=》46 – 22 – 20 + 10 = 14
二:OpenCV中积分图函数
OpenCV中通过integral()函数可以很容易的计算图像的积分图,该函数支持和表积分图、平方和表积分图、瓦块和表积分图计算。integral函数与参数解释如下:
-
void cv::integral( -
InputArray src, // 输入图像 -
OutputArray sum, // 和表 -
OutputArray sqsum, // 平方和表 -
int sdepth = -1, // 和表数据深度常见CV_32S -
int sqdepth = -1 // 平方和表数据深度 常见 CV_32F -
)
三:使用积分图函数
通过代码演示计算积分图实现任意窗口大小的盒子模糊与垂直边缘提取,完整的代码实现如下:
-
#include -
#include -
-
using namespace cv; -
using namespace std; -
-
void blur_demo(Mat &image, Mat &sum); -
void edge_demo(Mat &image, Mat &sum); -
int getblockSum(Mat &sum, int x1, int y1, int x2, int y2, int i); -
int main(int argc, char** argv) { -
Mat src = imread("D:/vcprojects/images/yuan_test.png"); -
if (src.empty()) { -
printf("could not load image... "); -
return -1; -
} -
namedWindow("input", CV_WINDOW_AUTOSIZE); -
imshow("input", src); -
-
namedWindow("output", CV_WINDOW_AUTOSIZE); -
-
// 计算积分图 -
Mat sum, sqrsum; -
integral(src, sum, sqrsum, CV_32S, CV_32F); -
-
// 积分图应用 -
int type = 0; -
while (true) { -
char c = waitKey(100); -
if (c > 0) { -
type = (int)c; -
printf("c : %d ", type); -
} -
-
if (c == 27) { -
break; // ESC -
} -
if (type == 49) { // 数字键 1 -
blur_demo(src, sum); -
} -
else if (type == 50) { // 数字键 2 -
edge_demo(src, sum); -
} -
else { -
blur_demo(src, sum); -
} -
} -
-
waitKey(0); -
return 0; -
} -
-
void blur_demo(Mat &image, Mat &sum) { -
int w = image.cols; -
int h = image.rows; -
Mat result = Mat::zeros(image.size(), image.type()); -
int x2 = 0, y2 = 0; -
int x1 = 0, y1 = 0; -
int ksize = 5; -
int radius = ksize / 2; -
int ch = image.channels(); -
int cx = 0, cy = 0; -
for (int row = 0; row < h + radius; row++) { -
y2 = (row + 1)>h ? h : (row + 1); -
y1 = (row - ksize) < 0 ? 0 : (row - ksize); -
for (int col = 0; col < w + radius; col++) { -
x2 = (col + 1)>w ? w : (col + 1); -
x1 = (col - ksize) < 0 ? 0 : (col - ksize); -
cx = (col - radius) < 0 ? 0 : col - radius; -
cy = (row - radius) < 0 ? 0 : row - radius; -
int num = (x2 - x1)*(y2 - y1); -
for (int i = 0; i < ch; i++) { -
// 积分图查找和表,计算卷积 -
int s = getblockSum(sum, x1, y1, x2, y2, i); -
result.at<Vec3b>(cy, cx)[i] = saturate_cast(s / num); -
} -
} -
} -
imshow("output", result); -
imwrite("D:/result.png", result); -
} -
-
/** -
* 3x3 sobel 垂直边缘检测演示 -
*/ -
void edge_demo(Mat &image, Mat &sum) { -
int w = image.cols; -
int h = image.rows; -
Mat result = Mat::zeros(image.size(), CV_32SC3); -
int x2 = 0, y2 = 0; -
int x1 = 0, y1 = 0; -
int ksize = 3; // 算子大小,可以修改,越大边缘效应越明显 -
int radius = ksize / 2; -
int ch = image.channels(); -
int cx = 0, cy = 0; -
for (int row = 0; row < h + radius; row++) { -
y2 = (row + 1)>h ? h : (row + 1); -
y1 = (row - ksize) < 0 ? 0 : (row - ksize); -
for (int col = 0; col < w + radius; col++) { -
x2 = (col + 1)>w ? w : (col + 1); -
x1 = (col - ksize) < 0 ? 0 : (col - ksize); -
cx = (col - radius) < 0 ? 0 : col - radius; -
cy = (row - radius) < 0 ? 0 : row - radius; -
int num = (x2 - x1)*(y2 - y1); -
for (int i = 0; i < ch; i++) { -
// 积分图查找和表,计算卷积 -
int s1 = getblockSum(sum, x1, y1, cx, y2, i); -
int s2 = getblockSum(sum, cx, y1, x2, y2, i); -
result.at<Vec3i>(cy, cx)[i] = saturate_cast(s2 - s1); -
} -
} -
} -
Mat dst, gray; -
convertScaleAbs(result, dst); -
normalize(dst, dst, 0, 255, NORM_MINMAX); -
cvtColor(dst, gray, COLOR_BGR2GRAY); -
imshow("output", gray); -
imwrite("D:/edge_result.png", gray); -
} -
-
int getblockSum(Mat &sum, int x1, int y1, int x2, int y2, int i) { -
int tl = sum.at<Vec3i>(y1, x1)[i]; -
int tr = sum.at<Vec3i>(y2, x1)[i]; -
int bl = sum.at<Vec3i>(y1, x2)[i]; -
int br = sum.at<Vec3i>(y2, x2)[i]; -
int s = (br - bl - tr + tl); -
return s; -
}
这里最重要的是要注意到上面的图示,积分图对象的Mat(1,1)对应实际图像Mat(0,0),如果不加处理的话会导致结果有明显的中心迁移。edge_demo实现了积分图查找提取图像边缘、blur_demo函数实现积分图查找图像均值模糊,getblockSum函数实现和表查找功能,运行显示:
原图:
模糊效果

边缘效果

审核编辑 :李倩
-
图像
+关注
关注
2文章
1095浏览量
42157 -
函数
+关注
关注
3文章
4406浏览量
66838 -
OpenCV
+关注
关注
33文章
651浏览量
44420
原文标题:OpenCV中积分图介绍与应用
文章出处:【微信号:CVSCHOOL,微信公众号:OpenCV学堂】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
零成本钢铁侠手套!树莓派+OpenCV 秒变手势遥控器!
如何使用树莓派与OpenCV实现面部和运动追踪的云台系统?
如何使用树莓派+OpenCV实现姿态估计和面部特征点追踪?
如何板端编译OpenCV并搭建应用--基于瑞芯微米尔RK3576开发板
ElfBoard技术贴|如何在【RK3588】ELF 2开发板中安装openCV4以及第三方库contrib
【Milk-V Duo S 开发板免费体验】SDK编译、人脸检测、OpenCV测试
itop-3568开发板机器视觉opencv开发手册-图像绘制-画线
在matlab中如何计算含有第一类修正的贝塞尔函数的积分算不出的问题?
快速部署!米尔全志T527开发板的OpenCV行人检测方案指南
为LSDK构建opencv时遇到的问题求解
运算放大器积分电路分析
使用OpenVINO™模型的OpenCV进行人脸检测,检测到多张人脸时,伺服电机和步入器电机都发生移动是为什么?
【AI实战项目】基于OpenCV的“颜色识别项目”完整操作过程

OpenCV中积分图函数与应用
评论