언어/C

C언어 영상처리 다양한 필터

이게될까 2024. 4. 17. 21:48
728x90
728x90

이미지 처리에서 사용할 수 있는 다양한 필터들이 있으며, 각각 특정 종류의 노이즈와 상황에 따라 장단점이 있습니다. 여기서 몇 가지 일반적인 필터들을 소개하고, 각각의 용도와 추천 상황에 대해 설명하겠습니다.

1. 평균 필터 (Mean Filter)

  • 설명: 주변 픽셀의 평균 값을 사용하여 현재 픽셀 값을 대체합니다.
  • 장점: 간단하고, 연산 속도가 빠릅니다.
  • 단점: 에지(edge)가 흐려질 수 있으며, 극단적인 노이즈에는 효과가 제한적입니다.
  • 적합한 사용 경우: 이미지에서 무작위 노이즈를 감소시키고 싶을 때, 그러나 에지 보존이 중요하지 않은 경우.

2. 미디언 필터 (Median Filter)

  • 설명: 주변 픽셀들을 크기 순으로 정렬한 후 중앙값을 선택하여 현재 픽셀을 대체합니다.
  • 장점: 솔트 앤 페퍼 노이즈와 같은 극단적 노이즈 제거에 매우 효과적입니다. 에지 보존에도 비교적 좋습니다.
  • 단점: 계산 비용이 평균 필터보다 높습니다.
  • 적합한 사용 경우: 솔트 앤 페퍼 노이즈 제거, 일반적인 노이즈 제거에서도 사용 가능하며 에지를 어느 정도 보존하면서 노이즈를 제거하고 싶을 때.

3. 가우시안 필터 (Gaussian Filter)

  • 설명: 가우스 함수를 기반으로 한 가중치 평균을 사용하여 픽셀을 스무딩합니다. 이 필터는 픽셀 주위의 거리에 따라 가중치를 다르게 적용합니다.
  • 장점: 자연스러운 이미지 스무딩 효과, 에지 근처에서도 성능이 우수합니다.
  • 단점: 극단적인 노이즈에는 그다지 효과적이지 않습니다.
  • 적합한 사용 경우: 자연스러운 스무딩이 필요하거나, 에지를 손상시키지 않으면서 전반적인 이미지 노이즈를 줄이고자 할 때.

추천

  • 일반적인 노이즈와 솔트 앤 페퍼 노이즈 처리: 미디언 필터를 추천합니다. 이는 극단적인 노이즈 제거에 효과적이며, 에지도 어느 정도 보존할 수 있습니다.
  • 자연스럽고 부드러운 스무딩: 가우시안 필터를 사용하면 좋습니다. 이는 더욱 자연스러운 이미지 처리에 적합하며, 보다 섬세한 스무딩이 필요할 때 유용합니다.

각 필터는 특정 상황과 요구 사항에 따라 선택할 수 있으며, 때로는 여러 필터를 조합하여 사용하기도 합니다. 노이즈의 종류와 이미지의 특성을 고려하여 가장 적절한 필터를 선택하는 것이 중요합니다.

이미지 처리에서 사용되는 다양한 필터링 기법이 있으며, 각기 다른 특성과 용도를 가지고 있습니다. 다음은 다섯 가지 추가적인 필터 유형에 대한 설명과 각각의 장단점입니다.

1. 라플라시안 필터 (Laplacian Filter)

  • 설명: 라플라시안 필터는 이미지의 두 번째 공간 파생값을 이용하여 에지 강화에 주로 사용됩니다. 이 필터는 이미지의 세밀한 부분과 에지에 대한 대비를 증가시키는 데 효과적입니다.
  • 장점: 에지 강화에 매우 효과적이며, 세밀한 이미지 디테일을 부각시킬 수 있습니다.
  • 단점: 노이즈에 매우 민감하며, 필터링 과정에서 노이즈가 강화될 수 있습니다.
  • 적합한 사용 경우: 에지 검출과 이미지 세부 정보 강화가 필요할 때 사용하지만, 노이즈가 적은 이미지에서 주로 사용됩니다.

2. 소벨 필터 (Sobel Filter)

  • 설명: 소벨 필터는 이미지의 x와 y 방향의 1차 미분을 이용하여 에지를 감지합니다. 이는 주로 수평 및 수직 방향의 에지 강조에 사용됩니다.
  • 장점: 간단하고 효과적인 에지 감지 방법을 제공하며, 에지의 방향성을 파악하기에 좋습니다.
  • 단점: 대각선 방향의 에지 감지에는 다소 제한적일 수 있습니다.
  • 적합한 사용 경우: 에지 강화 및 감지가 중요한 이미지 처리에서 활용됩니다.

3. 슈마흐 필터 (Scharr Filter)

  • 설명: 슈마흐 필터는 소벨 필터와 유사하지만, 대각선 에지 감지에 더 강화된 민감도를 제공합니다.
  • 장점: 더 정확하고 민감한 에지 감지가 가능하며, 에지 방향에 덜 민감합니다.
  • 단점: 계산 비용이 소벨 필터보다 높을 수 있습니다.
  • 적합한 사용 경우: 고해상도 이미지에서 더 세밀한 에지 감지가 필요할 때 사용됩니다.

4. 빌라트럴 필터 (Bilateral Filter)

  • 설명: 빌라트럴 필터는 가우시안 필터를 확장한 형태로, 가까운 픽셀 뿐만 아니라 픽셀 간의 강도 차이를 고려하여 스무딩을 진행합니다.
  • 장점: 에지를 보존하면서 이미지를 효과적으로 스무딩할 수 있습니다.
  • 단점: 계산 비용이 매우 높고 처리 속도가 느립니다.
  • 적합한 사용 경우: 에지 보존이 중요한 동시에 노이즈 제거가 필요한 경우에 적합합니다.

5. 와이너 필터 (Wiener Filter)

  • 설명: 와이너 필터는 주파수 영역에서 이미지를 복원하는 데 사용되며, 이미지의 원래 신호를 복원하고자 할 때 주로 사용됩니다.
  • 장점: 블러링과 노이즈를 효과적으로 제거할 수 있으며, 이미지 복원에 효과적입니다.
  • 단점: 모델 파라미터를 정확히 설정해야 하며, 잘못 설정할 경우 복원 효과가 떨어질 수 있습니다.
  • 적합한 사용 경우: 이미지가 블러링되었거나, 노이즈가 섞인 경우 이미지를 복원하는데 사용됩니다.

이와 같은 필터들은 각각 특정 상황에 맞춰서 선택되어야 합니다. 처리해야 할 이미지의 특성과 요구하는 결과에 따라 가장 적절한 필터를 선택하는 것이 중요합니다.

앞서 설명한 다섯 가지 필터 각각을 C 코드로 작성하는 것은 상당히 복잡할 수 있습니다. 여기서는 각 필터의 기본적인 로직을 C 언어로 구현하는 방법을 간단히 설명하겠습니다. 이들을 실제 프로젝트에 통합하기 전에는 추가적인 최적화와 에러 처리를 고려해야 합니다.

1. 소벨 필터 (Sobel Filter)

소벨 필터는 에지 감지에 주로 사용되며, x와 y 방향의 미분을 기반으로 합니다.

#include <stdio.h>
#include <stdlib.h>

void applySobelFilter(double *src, double *dst, int width, int height) {
    int Gx[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
    int Gy[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};
    int i, j, k, l;

    for (i = 1; i < height - 1; i++) {
        for (j = 1; j < width - 1; j++) {
            double sumX = 0, sumY = 0;
            for (k = -1; k <= 1; k++) {
                for (l = -1; l <= 1; l++) {
                    sumX += src[(i + k) * width + (j + l)] * Gx[k + 1][l + 1];
                    sumY += src[(i + k) * width + (j + l)] * Gy[k + 1][l + 1];
                }
            }
            dst[i * width + j] = sqrt(sumX * sumX + sumY * sumY);
        }
    }
}

2. 빌라트럴 필터 (Bilateral Filter)

빌라트럴 필터는 이미지의 부드러움을 유지하면서 에지를 보존합니다. 이 예제는 그 기본적인 형태만 다룹니다.

#include <math.h>

double gaussian(double x, double sigma) {
    return exp(-(x * x) / (2 * sigma * sigma));
}

void applyBilateralFilter(double *src, double *dst, int width, int height, double sigma_d, double sigma_r) {
    int i, j, k, l;
    int size = 3; // Filter size
    int half_size = size / 2;

    for (i = half_size; i < height - half_size; i++) {
        for (j = half_size; j < width - half_size; j++) {
            double weight_sum = 0, response = 0;

            for (k = -half_size; k <= half_size; k++) {
                for (l = -half_size; l <= half_size; l++) {
                    double spatial = gaussian(sqrt(k * k + l * l), sigma_d);
                    double range = gaussian(src[(i + k) * width + (j + l)] - src[i * width + j], sigma_r);
                    double weight = spatial * range;
                    weight_sum += weight;
                    response += weight * src[(i + k) * width + (j + l)];
                }
            }

            dst[i * width + j] = response / weight_sum;
        }
    }
}

3. 슈마흐 필터 (Scharr Filter)

슈마흐 필터의 구현은 소벨 필터와 유사하지만, 특정 방향에 대한 감도가 더 높습니다. 여기에서는 구현을 생략하겠습니다.

4. 라플라시안 필터 (Laplacian Filter)

라플라시안 필터는 두 번째 미분을 사용하여 이미지에서 빠르게 변화하는 부분을 강조합니다.

void applyLaplacianFilter(double *src, double *dst, int width, int height) {
    int kernel[3][3] = {{0, 1, 0}, {1, -4, 1}, {0, 1, 0}};
    int i, j, k, l;

    for (i = 1; i < height - 1; i++) {
        for (j = 1; j < width - 1; j++) {
            double sum = 0;
            for (k = -1; k <= 1; k++) {
                for (l = -1; l <= 1; l++) {
                    sum += src[(i + k) * width + (j + l)] * kernel[k + 1][l + 1];
                }
            }
            dst[i * width + j] = sum;
        }
    }
}

5. 와이너 필터 (Wiener Filter)

와이너 필터는 주로 신호나 이미지 복원에 사용됩니다. 복잡한 주파수 영역 처리가 포함되어, 여기에서 간단한 구현을 제공하는 것은 불가능합니다.

결론

이 필터들의 각 구현은 상당히 기초적이며, 실제 응용에서는 더 많은 최적화와 예외 처리가 필요합니다. 또한, 다양한 필터링 기법을 조합하여 사용할 수 있으며, 특정 애플리케이션의 요구에 맞추어 필터의 파라미터를 조정해야 할 수도 있습니다. 각 필터의 특성을 이해하고, 적절한 상황에서 최적의 필터를 선택하는 것이 중요합니다.

노이즈 제거를 위해 사용할 수 있는 필터는 다양하며, 각각 특정 유형의 노이즈에 대해 더 적합하거나 특별한 기능을 수행할 수 있습니다. 다음은 평균 필터와 가우시안 필터 외에 추천할 수 있는 10가지 필터입니다:

  1. 미디언 필터 (Median Filter):
    • 솔트 앤 페퍼 노이즈 같은 극단적인 값에 강합니다. 각 픽셀 주변의 중간 값을 선택합니다.
  2. 양방향 필터 (Bilateral Filter):
    • 에지를 보존하면서 노이즈를 제거합니다. 공간적 근접성과 픽셀 간의 강도 차이 모두를 고려합니다.
  3. 와이너 필터 (Wiener Filter):
    • 통계적 접근을 사용하여 전체 이미지의 국소 평균과 분산을 기반으로 노이즈를 제거합니다.
  4. 안시로트로픽 디퓨전 필터 (Anisotropic Diffusion Filter):
    • 이미지의 에지를 유지하면서 노이즈를 제거합니다. 각 픽셀의 이웃과의 차이를 기반으로 확산 과정을 조절합니다.
  5. 논-로컬 민스 필터 (Non-Local Means Filter):
    • 이미지 내의 유사한 패치를 찾아 평균을 취함으로써 노이즈를 제거합니다. 이는 특히 질감이 복잡한 이미지에서 효과적입니다.
  6. Total Variation Denoising:
    • 이미지의 전체 변동을 최소화하면서 노이즈를 제거합니다. 이 기법은 이미지의 주요 구조를 유지하면서 스무딩합니다.
  7. Wavelet Transform:
    • 이미지를 다양한 주파수 성분으로 분해하고, 노이즈가 생길 가능성이 높은 성분만을 제거합니다.
  8. Guided Filter:
    • 가이드 이미지를 사용하여 주 이미지의 필터링을 수행합니다. 이는 에지 보존에 탁월하며, 디테일과 에지를 유지하면서 스무딩을 수행합니다.
  9. Adaptive Median Filter:
    • 필터의 크기를 동적으로 조절하여, 노이즈의 양에 따라 최적의 결과를 제공합니다.
  10. Recursive Least Squares Filter (RLS Filter):
    • 이미지의 노이즈 제거를 위해 재귀적 최소 제곱 추정을 사용합니다. 이 필터는 동적 시스템에서 주로 사용되지만, 이미지에서 노이즈 제거에도 적용할 수 있습니다.

각 필터는 특정 상황과 이미지 유형에 따라 다르게 최적화될 수 있으며, 필터링할 이미지의 특성에 맞춰 적절한 필터를 선택하는 것이 중요합니다. 이러한 필터들은 다양한 노이즈 유형과 이미지 처리 요구 사항을 충족할 수 있도록 다양한 방식으로 설계되었습니다.

기존 코드의 형식을 따라 각각의 필터 기능을 구현하는 함수를 만들어보겠습니다. 아래는 다양한 필터링 방법을 C언어로 구현한 예제입니다. 이 함수들은 주어진 이미지 데이터 py에 대한 필터링을 수행하고 결과를 y3에 저장합니다.

1. Bilateral Filter

양방향 필터는 이미지의 세부 사항을 유지하면서 노이즈를 제거합니다. 이 필터는 공간적 근접성과 픽셀 강도 차이를 모두 고려하여 노이즈를 제거하고, 에지를 보존합니다.

#include <math.h>
#include <stdlib.h>

double gaussian(double x, double sigma) {
    return exp(-0.5 * x * x / (sigma * sigma));
}

void calBilateralFilter(double* y3, double* py, int fsize, int height, int width, int pwidth, double sigma_s, double sigma_r) {
    int offset = fsize / 2;
    double* window = (double*)malloc(fsize * fsize * sizeof(double));
    double* weights = (double*)malloc(fsize * fsize * sizeof(double));

    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            double norm_factor = 0.0;
            double result = 0.0;
            int idx = 0;

            for (int dy = -offset; dy <= offset; dy++) {
                for (int dx = -offset; dx <= offset; dx++) {
                    int x = i + dx;
                    int y = j + dy;

                    if (x >= 0 && x < width && y >= 0 && y < height) {
                        double pixel_diff = py[j * pwidth + i] - py[y * pwidth + x];
                        double spatial_weight = gaussian(sqrt(dx * dx + dy * dy), sigma_s);
                        double range_weight = gaussian(pixel_diff, sigma_r);
                        weights[idx] = spatial_weight * range_weight;
                        window[idx] = py[y * pwidth + x];
                        norm_factor += weights[idx];
                        idx++;
                    }
                }
            }

            for (int k = 0; k < idx; k++) {
                result += window[k] * weights[k];
            }

            y3[j * width + i] = result / norm_factor;
        }
    }

    free(window);
    free(weights);
}

2. Total Variation Denoising

총 변동 최소화를 통해 이미지에서 노이즈를 제거하는 기술입니다. 이 코드는 간단한 버전으로 구현되었으며, 실제 사용시에는 더 정교한 최적화 알고리즘이 필요할 수 있습니다.

void calTotalVariationDenoising(double* y3, double* py, int height, int width, int pwidth, double lambda) {
    for (int j = 1; j < height - 1; j++) {
        for (int i = 1; i < width - 1; i++) {
            double px = py[j * pwidth + (i + 1)] - py[j * pwidth + i];
            double nx = py[j * pwidth + i] - py[j * pwidth + (i - 1)];
            double py = py[(j + 1) * pwidth + i] - py[j * pwidth + i];
            double ny = py[j * pwidth + i] - py[(j - 1) * pwidth + i];

            y3[j * width + i] = py[j * pwidth + i] + lambda * (px + nx + py + ny);
        }
    }
}

기존 코드와 호환되도록 와이너 필터 (Wiener Filter)안시로트로픽 디퓨전 필터 (Anisotropic Diffusion Filter)를 구현해보겠습니다. 이 두 필터는 이미지 노이즈 제거와 에지 보존에 효과적인 방법을 제공합니다.

1. 와이너 필터 (Wiener Filter)

와이너 필터는 로컬 평균과 분산을 사용하여 각 픽셀에 대한 최적의 추정을 수행합니다. 다음은 간단한 구현입니다:

#include <math.h>
#include <stdlib.h>

void calWienerFilter(double* y3, double* py, int fsize, int height, int width, int pwidth) {
    int offset = fsize / 2;
    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            double sum = 0.0, sumWeights = 0.0;
            double mean = 0.0, var = 0.0;

            // Calculate local mean
            for (int k = -offset; k <= offset; k++) {
                for (int l = -offset; l <= offset; l++) {
                    int nx = i + l, ny = j + k;
                    if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
                        mean += py[ny * pwidth + nx];
                        sumWeights += 1.0;
                    }
                }
            }
            mean /= sumWeights;

            // Calculate local variance
            for (int k = -offset; k <= offset; k++) {
                for (int l = -offset; l <= offset; l++) {
                    int nx = i + l, ny = j + k;
                    if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
                        double temp = py[ny * pwidth + nx] - mean;
                        var += temp * temp;
                    }
                }
            }
            var /= sumWeights;

            double noiseVariance = 0.01; // This is an assumption; in practice, it should be estimated
            var = max(var - noiseVariance, 0.01); // Avoid division by zero

            // Wiener filter
            for (int k = -offset; k <= offset; k++) {
                for (int l = -offset; l <= offset; l++) {
                    int nx = i + l, ny = j + k;
                    if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
                        y3[j * width + i] += (py[ny * pwidth + nx] - mean) * (var / (var + noiseVariance)) + mean;
                    }
                }
            }
            y3[j * width + i] /= sumWeights;
        }
    }
}

2. 안시로트로픽 디퓨전 필터 (Anisotropic Diffusion Filter)

안시로트로픽 디퓨전 필터는 이미지의 세부 사항을 유지하면서 노이즈를 감소시키는 방법입니다. 다음은 이를 구현한 코드입니다:

void calAnisotropicDiffusionFilter(double* y3, double* py, int height, int width, int pwidth, double lambda, int iterations) {
    double kappa = 30.0; // Contrast parameter
    memcpy(y3, py, width * height * sizeof(double));

    for (int it = 0; it < iterations; it++) {
        for (int j = 1; j < height-1; j++) {
            for (int i = 1; i < width-1; i++) {
                double north = py[(j-1) * pwidth + i];
                double south = py[(j+1) * pwidth + i];
                double east  = py[j * pwidth + (i+1)];
                double west  = py[j * pwidth + (i-1)];
                double center = py[j * pwidth + i];

                double cn = exp(-(fabs(center - north) / kappa));
                double cs = exp(-(fabs(center - south) / kappa));
                double ce = exp(-(fabs(center - east) / kappa));
                double cw = exp(-(fabs(center - west) / kappa));

                y3[j * width + i] = center + lambda * (cn * (north - center) + cs * (south - center) + ce * (east - center) + cw * (west - center));
            }
        }
        memcpy(py, y3, width * height * sizeof(double)); // Update py for the next iteration
    }
}

아래 코드는 주어진 C 코드와 호환되도록 Non-Local Means FilterTotal Variation Denoising 필터를 구현한 것입니다. 이러한 필터들은 이미지에서 노이즈를 줄이는 동시에 중요한 이미지 세부사항을 유지하는 데 유용합니다.

1. Non-Local Means Filter

논 로컬 민스 필터는 이미지의 유사한 패치를 찾아 평균을 취함으로써 노이즈를 제거합니다. 이는 특히 질감이 복잡한 이미지에서 효과적입니다.

#include <math.h>
#include <stdlib.h>

double euclidean_distance(double* a, double* b, int length) {
    double sum = 0.0;
    for (int i = 0; i < length; i++) {
        sum += (a[i] - b[i]) * (a[i] - b[i]);
    }
    return sqrt(sum);
}

void calNonLocalMeansFilter(double* y3, double* py, int height, int width, int pwidth, int fsize, double h) {
    int offset = fsize / 2;
    int templateSize = fsize * fsize;
    double* templateA = (double*)malloc(templateSize * sizeof(double));
    double* templateB = (double*)malloc(templateSize * sizeof(double));

    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            double weightSum = 0.0;
            double filteredValue = 0.0;

            // Extract template A centered at (i, j)
            int count = 0;
            for (int dy = -offset; dy <= offset; dy++) {
                for (int dx = -offset; dx <= offset; dx++) {
                    int nx = i + dx, ny = j + dy;
                    if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
                        templateA[count++] = py[ny * pwidth + nx];
                    }
                }
            }

            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    // Extract template B centered at (x, y)
                    count = 0;
                    for (int dy = -offset; dy <= offset; dy++) {
                        for (int dx = -offset; dx <= offset; dx++) {
                            int nx = x + dx, ny = y + dy;
                            if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
                                templateB[count++] = py[ny * pwidth + nx];
                            }
                        }
                    }

                    double dist = euclidean_distance(templateA, templateB, templateSize);
                    double weight = exp(-dist * dist / (h * h));
                    filteredValue += py[y * pwidth + x] * weight;
                    weightSum += weight;
                }
            }

            y3[j * width + i] = filteredValue / weightSum;
        }
    }

    free(templateA);
    free(templateB);
}

2. Total Variation Denoising

Total Variation Denoising는 이미지의 전체 변동을 최소화하면서 노이즈를 제거합니다.

void calTotalVariationDenoising(double* y3, double* py, int height, int width, int pwidth, double lambda) {
    // Total variation denoising
    for (int j = 1; j < height - 1; j++) {
        for (int i = 1; i < width - 1; i++) {
            double north = py[(j - 1) * pwidth + i];
            double south = py[(j + 1) * pwidth + i];
            double east = py[j * pwidth + (i + 1)];
            double west = py[j * pwidth + (i - 1)];
            double current = py[j * pwidth + i];
            double tv = lambda * (north + south + east + west - 4 * current);
            y3[j * width + i] = current + tv;
        }
    }
}

위의 구현들은 기본적인 로직을 제공합니다. 각 알고리즘은 매개변수와 알고리즘 세부사항에 따라 추가적인 최적화와 조정이 필요할 수 있습니다. 실제 응용 프로그램에서는 더 많은 최적화, 경계 처리, 그리고 메모리 관리가 필요할 수 있습니다.

제공된 코드는 Wavelet 변환과 Guided 필터 기술을 통합하기 위해 조정되었습니다. 이러한 방법들은 이미지 처리 작업에 사용되며, 노이즈 감소, 디테일 향상, 에지 보존과 같은 작업에 유용합니다.

1. 웨이블릿 변환을 위한 이미지 더노이징 (Wavelet Transform for Image Denoising)

웨이블릿 변환은 이미지에서 중요한 특징을 보존하면서 노이즈를 효과적으로 줄일 수 있습니다. 여기서는 하르 웨이블릿(Haar wavelet) 분해와 재구성의 간단한 예를 가정합니다. 실제 구현은 특정 웨이블릿 라이브러리 또는 변환의 수동 구현에 따라 달라질 수 있습니다.

#include <math.h>
#include <stdlib.h>

void calWaveletTransform(double* y3, double* py, int height, int width, int pwidth) {
    // 하르 웨이블릿 변환을 이용한 한 단계 분해
    for (int j = 0; j < height; j += 2) {
        for (int i = 0; i < width; i += 2) {
            double A = (py[j * pwidth + i] + py[j * pwidth + i + 1] + py[(j + 1) * pwidth + i] + py[(j + 1) * pwidth + i + 1]) / 4;  // 근사
            double H = (py[j * pwidth + i] - py[j * pwidth + i + 1] + py[(j + 1) * pwidth + i] - py[(j + 1) * pwidth + i + 1]) / 4;  // 수평 디테일
            double V = (py[j * pwidth + i] + py[j * pwidth + i + 1] - py[(j + 1) * pwidth + i] - py[(j + 1) * pwidth + i + 1]) / 4;  // 수직 디테일
            double D = (py[j * pwidth + i] - py[j * pwidth + i + 1] - py[(j + 1) * pwidth + i] + py[(j + 1) * pwidth + i + 1]) / 4;  // 대각선 디테일

            y3[j/2 * pwidth + i/2] = A; // 근사 계수 저장
            // 보통 H, V, D도 추가 처리나 전체 웨이블릿 분해를 위해 저장해야 함
        }
    }
}

2. 가이드 필터 (Guided Filter)

가이드 필터는 에지를 보존하는 스무딩 필터입니다. 이 필터는 양방향 필터보다 더 복잡하지만, 에지 보존 성능이 뛰어납니다.

#include <stdio.h>
#include <stdlib.h>

void calGuidedFilter(double* guide, double* src, double* dst, int height, int width, int pwidth, int radius, double eps) {
    double* mean_I = (double*)calloc(height * width, sizeof(double));
    double* mean_P = (double*)calloc(height * width, sizeof(double));
    double* corr_I = (double*)calloc(height * width, sizeof(double));
    double* corr_IP = (double*)calloc(height * width, sizeof(double));
    double* var_I = (double*)calloc(height * width, sizeof(double));
    double* cov_IP = (double*)calloc(height * width, sizeof(double));
    double* a = (double*)calloc(height * width, sizeof(double));
    double* b = (double*)calloc(height * width, sizeof(double));

    // 평균과 상관관계 계산 등 필요한 모든 단계를 포함하지 않음
    // 평균 I, 평균 P, 상

관 I, 상관 IP가 이미 계산되었다고 가정

    // 계수 'a'와 'b' 계산
    for (int i = 0; i < height * width; i++) {
        var_I[i] = corr_I[i] - mean_I[i] * mean_I[i];
        cov_IP[i] = corr_IP[i] - mean_I[i] * mean_P[i];
        a[i] = cov_IP[i] / (var_I[i] + eps);
        b[i] = mean_P[i] - a[i] * mean_I[i];
    }

    // 출력 계산
    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            dst[j * width + i] = a[j * width + i] * guide[j * pwidth + i] + b[j * width + i];
        }
    }

    free(mean_I);
    free(mean_P);
    free(corr_I);
    free(corr_IP);
    free(var_I);
    free(cov_IP);
    free(a);
    free(b);
}

이 예제들은 기본적인 로직을 제공하며, 실제 응용 프로그램에서는 매개변수 조정, 경계 처리 등 추가적인 최적화가 필요합니다.

728x90