더북(TheBook)

이 장에서 구현할 필터링 관련 함수들은 새로운 파일에 그 내용을 작성하도록 하자. 새로 추가할 파일의 이름은 IppFilter.h와 IppFilter.cpp 파일이다. Visual Studio에서 [프로젝트] > [새 항목 추가...] 메뉴를 선택하여 IppFilter.h 파일과 IppFilter.cpp 파일을 각각 추가하자.

평균 값 필터 구현 함수의 이름은 IppFilterMean을 사용하기로 하자. 그리고 소스 8-1과 같이 IppFilter.h 파일에 IppFilterMean 함수 선언을 추가하자.

소스 8-1 평균 값 필터 구현 함수 선언(IppFilter.h)
#pragma once

#include "IppImage.h"

void IppFilterMean(IppByteImage& imgSrc, IppByteImage& imgDst);

IppFilterMean 함수는 입력 영상 imgSrc에 대해 3×3 크기의 마스크를 이용한 평균 값 필터링을 수행하고, 그 결과를 imgDst에 저장한다. 이 책에서는 오직 3×3 크기의 필터 마스크를 사용한 필터링만을 구현할 것이다. 다양한 크기의 마스크를 이용한 평균 값 필터 함수는 여러분이 직접 구현해보기 바란다. IppFilterMean 함수의 전체 구현은 소스 8-2에 나타내었다.

소스 8-2 평균 값 필터 구현 함수(IppFilter.cpp)
#include "stdafx.h"
#include "IppFilter.h"

void IppFilterMean(IppByteImage& imgSrc, IppByteImage& imgDst)
{
    int w = imgSrc.GetWidth();
    int h = imgSrc.GetHeight();

    imgDst = imgSrc;

    BYTE** pSrc = imgSrc.GetPixels2D();
    BYTE** pDst = imgDst.GetPixels2D();

    int mask[3][3] = {
        { 1, 1, 1 },
        { 1, 1, 1 },
        { 1, 1, 1 },
    };

    int i, j, m, n, sum;
    for (j = 1; j < h - 1; j++)
    for (i = 1; i < w - 1; i++)
    {
        sum = 0;
        for (m = 0; m < 3; m++)
        for (n = 0; n < 3; n++)
        {
            sum += (pSrc[j - 1 + m][i - 1 + n] * mask[m][n]);
        }

        pDst[j][i] = static_cast<BYTE>(limit(sum / 9. + 0.5));
    }
}

IppFilterMean 함수에서 실제 마스크 연산을 수행하기 전에 imgSrcimgDst로 복사하는 코드에 주목하자.

imgDst = imgSrc;

위 코드가 수행되면 IppByteImage 클래스의 대입 연산자에 의해 imgSrc 영상이 imgDst 영상으로 복사된다. 이 후 for 루프 안에서 마스크 연산을 수행할 때, 원본 픽셀 값은 imgSrc 영상에서 참조하고 마스크 연산 결괏값은 imgDst 영상에 적어줌으로써 정상적인 필터링 결과를 얻을 수 있다. 게다가 최외곽 픽셀에 대해서는 마스크 연산을 수행하지 않기 때문에, 원본 영상의 최외곽 픽셀 값이 그대로 결과 영상으로 복사되는 효과도 있다.

소스 8-2에 나타난 IppFilterMean 함수에서는 마스크 연산을 위해서 전체 4중 for 루프를 사용하였다. 바깥쪽 i, j로 구성된 for 루프는 영상 전체를 순회하는 for 루프이고, 안쪽의 m, n으로 구성된 for 루프는 마스크 배열 mask를 순회하는 for 루프이다. 4중 for 루프 안에서 mask 배열을 참조하는 인덱스가 0보다 작거나 배열 크기보다 커지지 않도록 주의해서 코드를 작성해야 한다.

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