적분 영상(integral image)이란 쉽게 말해서 다음 픽셀에 이전 픽셀까지의 합이 더해진 영상이다. 즉, 다음과 같은 수식으로 표현되는데
여기서 integImage(x, y)는 적분 영상이고 orgImage(x', y')는 원래 영상이다.
적분 영상의 장점은 특정 영역의 픽셀 값의 총합을 매우 쉽게 구할 수 있다는 점이다.
다음의 그림을 보면 이해가 쉬울 것이다.
8*8 크기의 임의의 1채널 영상을 예로 든 것이다. 좌측 상단이 원점이다.
왼쪽의 원래 영상에서 칠해진 영역의 넓이는
오른쪽 적분 영상에서 녹색 영역의 합과 주황색 영역의 합을 뺀 것과 같다.
(물론, 위 영상 전체의 합은 2250으로, 적분 영상에서의 마지막 값과 같다.)
이것을 수식으로 나타내면 다음과 같다.
다음의 그림을 참고하면 원리를 알 수 있다.
D 영역의 픽셀 값을 얻기 위해서 점 d까지의 넓이에서 점 b까지의 넓이와 점 c까지의 넓이를 뺀 후
두 번 빼진 점 a 까지의 넓이를 한 번 더해줌으로써 D 영역의 넓이를 구할 수 있는 것이다.
( [D] = [A+B+C+D] - [A+C] - [A+B] + [A] )
이러한 적분 영상은 하나의 영상에 대해 특정 영역의 픽셀 값의 합을 여러 번 구해야 할 필요가 있을 때 유용하게 사용할 수 있다.
아래는 적분 영상을 구하는 C++ 함수의 예시(example)이다.
#define R 0xff0000
#define G 0x00ff00
#define B 0x0000ff
void integral_image(int* image_input, int w, int h)
{
int imgSize = w*h;
static int* image_input = new int[imgSize];
// 3채널(RGB) 영상을 기준으로 한다. 이진 영상 또는 그레이 영상에 대해서는 하나의 배열만 있으면 된다.
// 여기에 각 색상별 적분 영상이 저장되며, 이것은 예시이므로 저장 후 아무 작업도 하지 않는다.
static int* integral_red = new int[imgSize];
static int* integral_green = new int[imgSize];
static int* integral_blue = new int[imgSize];
int idx=0;
for ( int i=0; i < h; i++ )
{
for ( int j=0; j < w; j++ )
{
idx = i*w+j;
image_input[idx] = img[idx];
// 적분 영상을 만들어 보자.
// 색공간의 형태에 따라 비트 이동의 형태는 알맞게 고쳐야 한다.
if ( i == 0 )
{
if ( j == 0 )
{
integral_red[idx] = (image_input[idx] & R) >> 16;
integral_green[idx] = (image_input[idx] & G) >> 8;
integral_blue[idx] = (image_input[idx] & B);
}
else
{
integral_red[idx] = integral_red[idx-1] + ((image_input[idx]&R)>>16);
integral_green[idx] = integral_green[idx-1] + ((image_input[idx]&G)>>8);
integral_blue[idx] = integral_blue[idx-1] + ((image_input[idx]&B));
}
}
else
{
if ( j == 0 )
{
integral_red[idx] = integral_red[idx-w] + ((image_input[idx]&R)>>16);
integral_green[idx] = integral_green[idx-w] + ((image_input[idx]&G)>>8);
integral_blue[idx] = integral_blue[idx-w] + ((image_input[idx]&B));
}
else
{
integral_red[idx] = integral_red[idx-w]+integral_red[idx-1]
+ ((image_input[idx]&R)>>16) - integral_red[idx-w-1];
integral_green[idx] = integral_green[idx-w]+integral_green[idx-1]
+ ((image_input[idx]&G)>>8) - integral_green[idx-w-1];
integral_blue[idx] = integral_blue[idx-w]+integral_blue[idx-1]
+ ((image_input[idx]&B)) - integral_blue[idx-w-1];
}
}
}
}
}