728x90

웨이블릿 변환은 푸리에 변환과 마찬가지로 주파수 영역 분석 도구로 볼 수 있습니다. 푸리에와 다른 점은 시간에 따라 변화하는 위치 분석이 가능하다는 점 입니다. 영상처리 분야에서는 웨이블릿 변환을 이용하여 잡음제거, 압축, 경계선 검출, 다중 해상도 분석 등을 할 수 있습니다. 웨이블릿 변환 기술 설명에 대해서는 앞에 블로그를 참고해 보시면 좋을 듯 합니다.

 

2025.10.05 - [영상처리 기술] - 영상처리 웨이블릿 변환 Wavelet Transform: 시간-주파수 분석

2025.10.12 - [영상처리 기술] - 영상처리 웨이블릿 변환 Wavelet Transform 활용: 잡음 제거

 

OpenCV에는 직접적으로 웨이블릿 변환 할 수 있는 함수가 없습니다. 따라서 외부 라이브러리를 함께 사용해야 합니다. OpenCV를 활용할 수 있는 파이썬과 C언어 계열로 구분하여 활용할 수 있는 라이브러리를 설명하겠습니다.

 

파이썬을 통해 구현 시, OpenCV와 함께 사용할 수 있는 웨이블릿 변환 라이브러리로는 “PyWavelets” 이며, MIT licence 기반에 무료 오픈 소스 입니다. 아래에서는 기본적인 코드 활용과 결과를 볼 수 있으며, 이미지에 대해 웨이블릿 변환을 하면 저주파(Approximation: LL)와 고주파(Detail: LH, HL, HH)로 분리됩니다. 저주파는 물체의 전반적인 형상을 나타내며 고주파는 경계선을 의미하는데 LH는 수평 경계성분, HL은 수직 경계성분, HH는 대각 경계성분을 나타냅니다.

 

import matplotlib.pyplot as plt
import numpy as np

import pywt
import pywt.data

# Load image
original = pywt.data.camera()

# Wavelet transform of image, and plot approximation and details
titles = ['Approximation', ' Horizontal detail',
          'Vertical detail', 'Diagonal detail']
coeffs2 = pywt.dwt2(original, 'bior1.3')
LL, (LH, HL, HH) = coeffs2
fig = plt.figure(figsize=(12, 3))
for i, a in enumerate([LL, LH, HL, HH]):
    ax = fig.add_subplot(1, 4, i + 1)
    ax.imshow(a, interpolation="nearest", cmap=plt.cm.gray)
    ax.set_title(titles[i], fontsize=10)
    ax.set_xticks([])
    ax.set_yticks([])

fig.tight_layout()
plt.show()

 

 

 

C/C++를 이용하여 구현 시, WaveLib (github.com/rafat/wavelib)을 활용하여 테스트 해 볼수 있습니다. 아래는 예제 코드이며 파이썬 예제와 동일하게 DWT를 이용하여 저주파(LL)와 고주파 성분(LH, HL, HH)을 분리해 낼 수 있습니다.

 

#include <iostream>
#include <opencv2/opencv.hpp>
#include “../header/wavelib.h”

using namespace cv;
using namespace std;

int main() {
    // image read
    Mat img = imread("image.tif", IMREAD_GRAYSCALE);
    int rows = img.rows;  int cols = img.cols;

    // double type
    vector<double> data(rows * cols);
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            data[i * cols + j] = (double)img.at<uchar>(i, j);
        }
    }

    // wavelet transform 
    wave_object wave = wave_init("haar"); // haar
    wt2_object wt = wt2_init(wave, "dwt", rows, cols, 1);

    // 2D DWT
    setDWTExtension(wt, "sym");   // symmetric
    setWT2D(wt, data.data());     
    dwt2(wt);                     // DWT

    // coeffs
    double* LL = getApprox2D(wt); // Approximation
    double* LH= getHoriz2D(wt);   // Detail LH
    double* HL = getVert2D(wt);   // Detail HL
    double* HH= getDiag2D(wt);    // Detail HH

    // display
    Mat approx(rows/2, cols/2, CV_64F, LL);
    Mat horiz(rows/2, cols/2, CV_64F, LH);
    Mat vert(rows/2, cols/2, CV_64F, HL);
    Mat diag(rows/2, cols/2, CV_64F, HH);

    imshow("Approximation", approx / 255.0);
    imshow("Horizontal Detail", horiz / 255.0);
    imshow("Vertical Detail", vert / 255.0);
    imshow("Diagonal Detail", diag / 255.0);

    waitKey(0);

    // memory free
    wt2_free(wt);
    wave_free(wave);

    return 0;
}
728x90

+ Recent posts