积分图像

本篇主要介绍了以下内容

  • 何为积分图像
  • 如何计算积分图像
  • 基于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)$为该点的左上角的像素点之和。

computeRectangleWithAlpha.png

实际上这是一种预计算的技术,以空间换时间,类似灰度值变换之时常常用到的查找表(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)$$

  • (4)扫描图像一遍,积分图像$ii$就构造好了。

代码实现

 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的图像 lena.jpg

得到的积分图归一化后显示为 结果.png

references

【1】积分图-维基百科 【2】图像处理、分析与机器视觉 【3】积分图像-xiaoluo91-csdn


本文由芒果浩明发布,转载请注明来源。 本文链接:https://blog.mangoeffect.net/opencv/integral-image.html


微信公众号