Favicon

Image pyramids

Peponi2/13/20255m

C#
NugetPackageOpenCvSharp4GaussianLaplacian

1. Introduction

OpenCvSharp4는 이미지 크기 조절 기능을 제공하는데, Cv2.Resize()Cv2.PyrUp(), Cv2.PyrDown()을 제공한다. 이 문서에서는 Cv2.PyrUp(), Cv2.PyrDown()을 이용하여 가우시안, 라플라시안 피라미드를 만드는 방법에 대해 알아본다.

2. Gaussian pyramid

Cat picture by Manfred Richter

가우시안 피라미드는 동일한 이미지를 여러 크기로 생성하여 (일반적으로 점점 작은 크기의 이미지를 생성) 만든 것이다. 이를 이용하여 객체 추적, 이미지 결합 등에 활용할 수 있으며 작업 효율성과 정확성 향상을 꾀할 수 있다.

가우시안 피라미드 메서드인 Cv2.PyrUp(), Cv2.PyrDown()의 동작 방식은 다음과 같다.

  • Cv2.PyrUp() : Upsampling (추가되는 행렬은 0으로 채움) 이후 gaussian blur
  • Cv2.PyrDown() : Gaussian blur 후 downsampling (짝수 행렬 제거)

이 때 적용되는 gaussian kernel은 다음과 같다.

  • Cv2.PyrUp() 4256[1464141624164624362464162416414641]\dfrac{4}{256} \begin{bmatrix} 1&4&6&4&1\\ 4&16&24&16&4\\ 6&24&36&24&6\\ 4&16&24&16&4\\ 1&4&6&4&1 \end{bmatrix}
  • Cv2.PyrDown() 1256[1464141624164624362464162416414641]\dfrac{1}{256} \begin{bmatrix} 1&4&6&4&1\\ 4&16&24&16&4\\ 6&24&36&24&6\\ 4&16&24&16&4\\ 1&4&6&4&1 \end{bmatrix}

Gaussian blur를 적용하는 알고리즘으로 인해 샘플링을 반복할수록 고주파 성분이 떨어져 나가게 되며 (엣지가 무뎌진다) 저주파 성분이 강조되는 결과를 얻게 된다. 따라서 Cv2.PyrDown() 이후 Cv2.PyrUp()을 수행하더라도 원래 이미지로 돌아올 수는 없다.

OpenCV에서는 가우시안 피라미드를 한번에 생성할 수 있는 메서드를 제공하고 있는데, OpenCvSharp4에는 Cv2.BuildPyramid()라는 이름으로 등록되어 있다. maxlevel 인자를 통해 최대 레벨을 지정할 수 있으며 레벨이 높아질 수록 크기가 작아진다. (레벨 0이 원본 이미지와 같다)

Cv2.PyrDown()Cv2.PyrUp(), Cv2.BuildPyramid()를 사용하여 이미지 피라미드를 만드는 방법은 다음 코드를 참조한다.

// Image load
using var original = Cv2.ImRead(dialog.FileName);
 
// Sampling
using var downsampled = original.PyrDown();   // Width / 2, Height / 2
using var upsampled = original.PyrUp();          // Width * 2, Height * 2
 
// Making pyramid
// 레벨 0 (원본) ~ 레벨 4까지 총 5개가 pyramid에 할당됨
IEnumerable<Mat> pyramid = original.BuildPyramid(4);

TIP

단순히 크기 변경을 위해 사용하는 경우에는 Cv2.Resize()를 고려해볼 수 있다. 기술된 바와 같이 가우시안 피라미드의 경우 블러 효과가 같이 적용되기 때문에 성능 저하가 발생할 수도 있다.

3. Laplacian pyramid

Cat picture by Manfred Richter

라플라시안 피라미드는 가우시안 피라미드로부터 생성되며 residual (원본과 gaussian blur 이미지의 차이) 정보를 포함하고 있다. 고주파 성분 정보를 가지고 있는 것으로 이를 이용해 이미지 필터링 또는 압축, 복원 등에 활용할 수 있다. 앞의 예시로 서술된 바와 같이 Cv2.PyrDown() 이후 Cv2.PyrUp()을 수행하는 경우 원본 이미지와는 차이가 발생하게 되는데, 여기에 residual을 이용하면 조금 더 원본 이미지에 가깝게 만들 수 있다.

original, gaussian compare

라플라시안 피라미드를 만드는 방법은 다음 코드를 참조한다.

var current = Cv2.ImRead(dialog.FileName);
 
for (int i = 0; i < 4; i++)
{
    var downsampled = current.PyrDown();
 
    // 원본 크기로 다시 up
    using var blur = downsampled.PyrUp();
    
    // 크기 조정 (원본 이미지와 크기 다를 수 있음)
    using var resized = blur.Resize(current.Size());
 
    using var laplacian = new Mat();
 
    // Laplacian 계산
    Cv2.Subtract(current, resized, laplacian);
 
    // 계산된 이미지 저장
    Cv2.ImWrite($"laplacian{i}.png", laplacian);
 
    current = downsampled;
}

4. 참조 자료