더북(TheBook)

그러면 3차 회선 보간법을 이용한 영상의 크기 변환을 C/C++ 함수로 만들어보자. 3차 회선 보간법의 구현 함수의 이름은 IppResizeCubic을 사용하기로 하자. IppResizeCubic 함수에서는 내부적으로 cubic_interpolation이라는 함수를 사용할 것이다. 그러므로 다음 두 개의 함수 선언을 IppGeometry.h 파일에 추가하자.

void IppResizeCubic(IppByteImage& imgSrc, IppByteImage& imgDst, int nw, int nh);
double cubic_interpolation(double v1, double v2, double v3, double v4, double d);

IppResizeCubic 함수의 인자 구성은 앞에서 살펴보았던 IppResizeNearest 또는 IppResizeBilinear 함수와 동일하다. cubic_interpolation 함수는 그림 9-13에서 설명한 4개의 픽셀 값을 이용하여 결정된 값 v를 반환하는 함수이며, 함수 인자로 사용되는 변수 명은 그림 9-13에 표기된 기호와 동일하다. cubic_interpolation 함수는 IppResizeCubic 함수 내에서 모두 5번 호출된다. IppResizeCubiccubic_interpolation 함수의 전체 구현은 소스 9-6에 나타내었다.

소스 9-6 3차 회선 보간법을 이용한 크기 변환 구현 함수(IppGeometry.cpp)
void IppResizeCubic(IppByteImage& imgSrc, IppByteImage& imgDst, int nw, int nh)
{
    int w = imgSrc.GetWidth();
    int h = imgSrc.GetHeight();

    imgDst.CreateImage(nw, nh);

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

    int i, j, x1, x2, x3, x4, y1, y2, y3, y4;
    double v1, v2, v3, v4, v;
    double rx, ry, p, q;

    for (j = 0; j < nh; j++)
    for (i = 0; i < nw; i++)
    {
        rx = static_cast<double>(w - 1) * i / (nw - 1);
        ry = static_cast<double>(h - 1) * j / (nh - 1);

        x2 = static_cast<int>(rx);
        x1 = x2 - 1; if (x1 < 0) x1 = 0;
        x3 = x2 + 1; if (x3 >= w) x3 = w - 1;
        x4 = x2 + 2; if (x4 >= w) x4 = w - 1;
        p = rx - x2;

        y2 = static_cast<int>(ry);
        y1 = y2 - 1; if (y1 < 0) y1 = 0;
        y3 = y2 + 1; if (y3 >= h) y3 = h - 1;
        y4 = y2 + 2; if (y4 >= h) y4 = h - 1;
        q = ry - y2;

        v1 = cubic_interpolation(pSrc[y1][x1], pSrc[y1][x2], pSrc[y1][x3], pSrc[y1][x4], p);
        v2 = cubic_interpolation(pSrc[y2][x1], pSrc[y2][x2], pSrc[y2][x3], pSrc[y2][x4], p);
        v3 = cubic_interpolation(pSrc[y3][x1], pSrc[y3][x2], pSrc[y3][x3], pSrc[y3][x4], p);
        v4 = cubic_interpolation(pSrc[y4][x1], pSrc[y4][x2], pSrc[y4][x3], pSrc[y4][x4], p);

        v = cubic_interpolation(v1, v2, v3, v4, q);

        pDst[j][i] = static_cast<BYTE>(limit(v + 0.5));
    }
}

double cubic_interpolation(double v1, double v2, double v3, double v4, double d)
{
    double v, p1, p2, p3, p4;

    p1 = 2 * v2;
    p2 = -v1 + v3;
    p3 = 2 * v1 - 5 * v2 + 4 * v3 - v4;
    p4 = -v1 + 3 * v2 - 3 * v3 + v4;

    v = (p1 + d * (p2 + d * (p3 + d * p4))) / 2.;

    return v;
}

소스 9-6의 IppResizeCubic 함수 내부의 정수형 변수 x1~x4, y1~y4는 3차 회선 보간법에서 사용할 16개의 점들의 가로, 세로 좌표를 저장할 변수이다. 이 좌표들을 지정할 때, 영상의 크기를 벗어난 위치의 좌표를 저장하지 않도록 신경을 써주어야 한다. 앞에서 언급한 것과 같이 cubic_interpolation 함수를 4번 호출하여 v1~v4의 값을 결정하는 것을 볼 수 있는데, 이 값들은 그림 9-11에서 설명한 삼각형에 해당하는 곳에서의 픽셀 값의 추정치이다. 그리고 v1~v4 값과 실숫값 q를 이용하여 cubic_interpolation 함수를 한 번 더 호출하여 최종적으로 보간된 값 v를 얻어냄을 볼 수 있다. 실숫값 v는 반올림하여 정수형으로 변환하고, 그 값을 결과 영상의 픽셀 값으로 지정한다.

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