반응형
250x250
Notice
Recent Posts
Recent Comments
Link
«   2025/07   »
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)

치수 계산하기 - subpixel 본문

카테고리 없음

치수 계산하기 - subpixel

folcjin 2025. 6. 19. 14:32
728x90
반응형

Sub-pixel Edge Detection 기반의 고정밀 CD측정은 pixel-level 경계 검출의 한계를 넘어, 곡선 보간, Edge fitting, 또는 gradient interpolation 등을 이용하여 실제 구조의 경계선을 소수점 단위까지 정밀하게 추정하는 방법이다

원리
- Edge 검출: Sobel 또는 Canny로 초기 edge map 생성
- Gradient interpolation: 엣지 픽셀 주변에서 1차 또는 2차 곡선을 피팅하여 정확한 edge 위치를 소수점 단위로 추정
-
Edge pair 매칭: 좌/우 또는 위/아래 edge 쌍을 찾아 거리 계산
-
실측 크기 변환 (선택): pixel 단위를 μm 등으로 변환

 

예제

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

// subpixel edge 위치 추정 (1D interpolation)
double interpolateSubpixel(const Mat& grad, int row, int col) {
    if (col <= 0 || col >= grad.cols - 1)
        return col;  // 경계선일 경우 단순 pixel 위치 반환

    double g0 = grad.at<float>(row, col - 1);
    double g1 = grad.at<float>(row, col);
    double g2 = grad.at<float>(row, col + 1);

    double denominator = g0 - 2 * g1 + g2;
    if (abs(denominator) < 1e-5) return col;

    double offset = 0.5 * (g0 - g2) / denominator;
    return col + offset;
}

// Edge로부터 CD 측정
double measureSubpixelCD(const Mat& grad, const Mat& edges, int row) {
    vector<double> edgePositions;

    for (int col = 1; col < edges.cols - 1; ++col) {
        if (edges.at<uchar>(row, col) > 0) {
            double subpixelCol = interpolateSubpixel(grad, row, col);
            edgePositions.push_back(subpixelCol);
        }
    }

    if (edgePositions.size() < 2) return -1.0;

    // 가장 바깥쪽 edge를 CD 측정용으로 사용
    return abs(edgePositions.front() - edgePositions.back());
}

int main(int argc, char** argv) {
    if (argc < 2) {
        cout << "Usage: ./SubpixelCD <image_path>" << endl;
        return -1;
    }

    Mat src = imread(argv[1], IMREAD_GRAYSCALE);
    if (src.empty()) {
        cerr << "Failed to load image!" << endl;
        return -1;
    }

    // Sobel 경사도 계산 (x 방향)
    Mat gradX;
    Sobel(src, gradX, CV_32F, 1, 0, 3);

    // Canny edge
    Mat edges;
    Canny(src, edges, 50, 150);

    // 관심 영역의 수평 중간 라인 기준 CD 측정
    int midRow = src.rows / 2;
    double cd = measureSubpixelCD(gradX, edges, midRow);

    if (cd > 0)
        cout << "Subpixel Critical Dimension (CD): " << cd << " pixels" << endl;
    else
        cout << "Failed to detect valid edge pair." << endl;

    return 0;
}

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