本篇主要介绍了以下内容
- 何为积分图像
- 如何计算积分图像
- 基于opencv实现积分图像的构建
积分图像
积分图像(integral image),是一个快速且有效地计算图像网格区域和的数据结构和算法,得到的结果是一个可以描述图像的全局信息的矩阵。其原理是对某个区域网格内像素点之和,所以又称总和面积表(英语:summed area table,简称SAT)。其数学的描述为如下公式:
$$ii(i,j) = \sum_{k \leq i, l\leq j} f(k,l)$$
其中,$f$为原图像,即位置$(i,j)$处的积分图像值$ ii(i,j)$为该点的左上角的像素点之和。
实际上这是一种预计算的技术,以空间换时间,类似灰度值变换之时常常用到的查找表(look up table)。在得到积分图之后,理论上可以$O(1)$的时间得到图像任意一个矩形区域的总像素之和,如上图所示,如要计算阴影的区域的像素总和,设$A(x1,y1),B(x2,y2),C(x3,y3),D(x4,y4)$,则计算非常简单,只需要用C的积分图减去其余三个积分图:
$$S = ii(x3,x3) - ii(x1,y1) - ii(x2,y2) - ii(x3,y3)$$
计算积分图像
算法步骤如下
- (1)用$s(i,j)$表示行方向的累加和,初始化$s(i,-1) =0 $.
- (2)用$ii(i,j)$表示一个积分图像,初始化$ii(-1,j)=0$.
- (3)逐行扫描图像,递归使用下面的公式计算每个像素$(i,j)$的累加和s(i,j)和积分图像$ii(i,j)$的值
$$s(i,j) = s(i,j-1) + f(i,j)$$
$$ii(i,j) = ii(i-1, j) + s(i,j)$$
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
// integral-image.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include<vector>
#include <opencv2/opencv.hpp>
int main()
{
// load gray image
cv::Mat image = cv::imread("lena.jpg", 0);
if (image.empty())
{
return -1;
}
int row = image.rows;
int col = image.cols;
//---------- calculate the integral image---------
// step1: initialize s(i, -1) =0;
std::vector<std::vector<int> > s(row, std::vector<int>(col,0));
// step2: initialize ii(-1, j) = 0;
std::vector<std::vector<int> > ii(row, std::vector<int>(col, 0));
// step3: calculate s(i,j) and ii(i,j)
for (auto i = 0; i < row; i++)
{
for (auto j = 0; j < col; j++)
{
// s(i,j) = s(i,j -1) + f(i,j)
if (j < 1)
{
s[i][j] = 0 + image.at<uchar>(i, j);//s(i, -1) =0;
}
else
{
s[i][j] = s[i][j - 1] + image.at<uchar>(i, j);
}
// ii(i,j) = ii(i-1, j) + s(i,j)
if (i < 1)
{
ii[i][j] = 0 + s[i][j];//ii(-1, j) = 0;
}
else
{
ii[i][j] = ii[i - 1][j] + s[i][j];
}
}
}
// normalize and show the integral image
double max = ii[row - 1][col - 1];
cv::Mat integral_image = cv::Mat(cv::Size(col, row), CV_8UC1);
for (auto i = 0; i < row; i++)
{
for (auto j = 0; j < col; j++)
{
ii[i][j] = int(double(ii[i][j] / max) * 255);
integral_image.at<uchar>(i,j) = ii[i][j];
}
}
cv::imshow("integral-image", integral_image);
cv::waitKey(0);
return 0;
}
|
计算lena的图像
得到的积分图归一化后显示为
references
【1】积分图-维基百科
【2】图像处理、分析与机器视觉
【3】积分图像-xiaoluo91-csdn
本文由芒果浩明发布,转载请注明来源。
本文链接:https://blog.mangoeffect.net/opencv/integral-image.html