반응형
250x250
Notice
Recent Posts
Recent Comments
Link
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

폴크(FOLC)

치수 계산하기 - robust edge detection 본문

카테고리 없음

치수 계산하기 - robust edge detection

folcjin 2025. 6. 21. 19:39
728x90
반응형

Gaussian Smoothing
노이즈를 제거하여 edge 검출의 안정성을 향상시키기 위한 가우시안 필터 적용.

1차 미분 (1st Derivative)
프로파일의 기울기를 계산하여 edge 후보 위치를 검출.

Zero-Crossing 위치 검출
1차 미분 결과가 양→음 또는 음→양으로 바뀌는 지점을 zero-crossing으로 판단.

Subpixel Interpolation
Zero-crossing 근처의 값을 가지고 2차 (Quadratic) 보간을 통해 subpixel 수준의 edge 위치를 계산.

 

예제

#include <iostream>
#include <vector>
#include <cmath>

// Gaussian smoothing (1D)
std::vector<double> gaussianSmooth(const std::vector<double>& input, double sigma) {
    int radius = static_cast<int>(std::ceil(3 * sigma));
    int size = 2 * radius + 1;
    std::vector<double> kernel(size);
    std::vector<double> output(input.size());

    // Generate kernel
    double sum = 0.0;
    for (int i = -radius; i <= radius; ++i) {
        kernel[i + radius] = std::exp(-0.5 * (i * i) / (sigma * sigma));
        sum += kernel[i + radius];
    }
    for (auto& k : kernel) k /= sum;

    // Apply convolution
    for (size_t i = 0; i < input.size(); ++i) {
        double acc = 0.0;
        for (int j = -radius; j <= radius; ++j) {
            int idx = std::clamp<int>(i + j, 0, input.size() - 1);
            acc += input[idx] * kernel[j + radius];
        }
        output[i] = acc;
    }
    return output;
}

// Compute 1st derivative
std::vector<double> computeDerivative(const std::vector<double>& profile) {
    std::vector<double> deriv(profile.size(), 0.0);
    for (size_t i = 1; i < profile.size() - 1; ++i) {
        deriv[i] = (profile[i + 1] - profile[i - 1]) / 2.0;
    }
    return deriv;
}

// Quadratic interpolation for subpixel zero-crossing
double quadraticSubpixel(const std::vector<double>& deriv, int idx) {
    double y1 = deriv[idx - 1];
    double y2 = deriv[idx];
    double y3 = deriv[idx + 1];

    double denom = (y1 - 2 * y2 + y3);
    if (std::abs(denom) < 1e-10) return idx; // avoid divide by zero

    double delta = 0.5 * (y1 - y3) / denom;
    return idx + delta;
}

// Main edge detection
std::vector<double> detectEdgesSubpixel(const std::vector<double>& input, double sigma) {
    std::vector<double> smoothed = gaussianSmooth(input, sigma);
    std::vector<double> deriv = computeDerivative(smoothed);

    std::vector<double> edgePositions;
    for (size_t i = 1; i < deriv.size() - 1; ++i) {
        if (deriv[i] * deriv[i + 1] < 0) {
            double subpixelPos = quadraticSubpixel(deriv, i);
            edgePositions.push_back(subpixelPos);
        }
    }
    return edgePositions;
}

// Example
int main() {
    std::vector<double> profile = {0, 0, 1, 3, 7, 12, 7, 3, 1, 0, 0};
    double sigma = 1.0;

    std::vector<double> edges = detectEdgesSubpixel(profile, sigma);

    for (double e : edges) {
        std::cout << "Edge at: " << e << std::endl;
    }

    return 0;
}

728x90
반응형
사업자 정보 표시
사업자 등록번호 : -- | TEL : --