더북(TheBook)

6.3.2 감마 보정 구현

감마 보정을 구현하는 방법은 간단하다. 앞에서 소개한 수식대로 모든 픽셀에 대하여 지수 법칙 변환을 해주면 된다. 다만 앞서 설명한 지수 법칙 변환의 입력 값 범위가 0부터 1 사이의 실숫값이기 때문에 영상의 그레이스케일 값에 적용하려면 적당한 크기로 스케일링을 해야 한다. 픽셀의 그레이스케일 값이 k라면 입력 값은 k/255로 줄여서 입력하고, 출력 값은 다시 k×255 형태로 크기를 키워주어야 한다. 그러므로 실제 영상에 대해 감마 보정을 구현하려면 다음의 수식처럼 사용해야 한다.

위 수식에서 γ 값이 역수의 형태(1/γ)로 쓰여져 있음을 유의하기 바란다.

그러면 실제 영상의 감마 보정을 위한 함수를 작성해보도록 하자. 감마 보정을 위한 함수 이름은 IppGammaCorrection을 사용하기로 하고, IppEnhance.h 파일에 다음과 같은 함수의 선언을 추가하자.

void IppGammaCorrection(IppByteImage& img, float gamma);

IppGammaCorrection 함수는 IppByteImage 객체의 참조형인 imgfloat 타입의 감마 값 gamma를 인자로 받는다. 감마 보정 결과는 다시 img에 저장된다. IppGammaCorrection 함수의 전체 구현은 소스 6-11에 나타내었다.

소스 6-11 감마 보정 함수(IppEnhance.cpp)
#include <math.h>void IppGammaCorrection(IppByteImage& img, float gamma)
{
    float inv_gamma = 1.f / gamma;

    int size = img.GetSize();
    BYTE* p = img.GetPixels();

    for (int i = 0; i < size; i++)
    {
        p[i] = static_cast<BYTE>(limit((pow(p[i] / 255.f, inv_gamma) * 255 + 0.5f)));
    }
}

IppGammaCorrection 함수의 for 루프 안에서 모든 픽셀에 대한 지수 변환을 수행하는 것을 볼 수 있다. 실숫값에 대한 지수 연산을 위해 C/C++ 함수인 pow 함수를 사용하였다. 지수 변환을 한 후, 맨 마지막에 0.5f를 더해준 것은 BYTE 타입으로 형변환할 때 반올림 효과를 주기 위함이다. pow 함수를 사용하기 위해 IppEnhance.cpp 파일 상단에는 #include <math.h> 문장을 추가하였다.

소스 6-11의 구현에서 함수 성능을 개선할 수 있는 한 가지 방법에 대해 좀 더 살펴보자. 지수 연산을 위해 for 루프 안에서 모든 픽셀에 대해 pow 함수가 사용되었는데, pow 함수가 적지 않은 연산 시간을 필요로 한다는 점이다. 물론 256×256 크기의 영상에 대해 IppGammaCorrection 함수를 실행해보면 눈 깜박할 시간에 결과 영상이 나타날 것이다. 그러나 보다 큰 영상에 대해 감마 보정을 수행한다거나 동영상에서 매 프레임에 대해 감마 보정을 수행하는 등의 작업 시에는 함수가 최대한 빠르게 동작하도록 소스 코드를 최적화하는 것이 좋다.

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