더북(TheBook)

마스크 연산을 구현할 경우 영상 처리 초보자들이 흔히 하는 실수는 입력 영상의 복사본을 사용하지 않는다는 점이다. 다음의 코드를 살펴보자.

BYTE** ptr = img.GetPixels2D();

double m[3][3];
// 마스크 m의 값 설정

double temp;
for (j = 1; j < h - 1; j++)
for (i = 1; i < w - 1; i++)
{
    temp = ptr[j - 1][i - 1] * m[0][0] + ptr[j - 1][i] * m[0][1] + ptr[j - 1][i + 1] * m[0][2]
        + ptr[j][i - 1] * m[1][0] + ptr[j][i] * m[1][1] + ptr[j][i + 1] * m[1][2]
        + ptr[j + 1][i - 1] * m[2][0] + ptr[j + 1][i] * m[2][1] + ptr[j + 1][i + 1] * m[2][2];
    ptr[j][i] = static_cast<BYTE>(limit(temp));
}

위 코드에서 img는 입력 영상을 나타내고, m 배열은 마스크를 의미한다. 최외곽 픽셀을 마스크 연산에서 제외하기 위하여 for 루프는 1부터 h - 2, 또는 1부터 w - 2까지 증가한다. 마스크를 나타내는 m 배열은 -1의 인덱스를 가질 수 없기 때문에, 배열 m의 인덱스는 0부터 2까지 증가하도록 설정하였다. 자, 위의 코드에서 문제점을 발견하였는가? 위 코드는 분명히 문법적인 에러는 발생시키지 않는다. 또한 앞에서 설명한 마스크 연산 수식을 정확하게 C/C++로 구현하였다. 그러나 위 코드는 비정상적인 결과 영상을 생성한다. 왜냐하면 for 루프 안에서 좌표에 대해 마스크 연산을 수행할 때, 이미 이전 루프에서 수정된 픽셀 값을 사용하고 있기 때문이다. 그림 8-4를 살펴보자.

그림 8-4 마스크 연산 시 이미 연산이 수행된 픽셀들

그림 8-4에서 (x, y)픽셀의 주변 픽셀 중 빗금이 쳐 있는 네 개의 픽셀은 이미 마스크 연산에 의해서 원본 영상의 값이 교체된 상태이다. 위의 프로그램 코드대로 계산할 경우, 원본 영상의 픽셀 값이 아니라 이미 마스크 연산을 거쳐서 결정된 결과 영상의 픽셀 값들이 사용되기 때문에 부정확한 연산이 수행되는 것이다. 그러므로 이 경우에는 입력 영상 img와 동일한 복사본 영상을 만들어서 픽셀 값을 참조하여야 한다. 이에 대한 구체적인 프로그램 코드의 구현 방법은 다음 절에서 제시하도록 하겠다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.