반응형
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)

치수 계산하기 - subpixel - accuracy 본문

카테고리 없음

치수 계산하기 - subpixel - accuracy

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

CD 측정 같은 선형 구조 분석에는 오히려 1D 프로파일 기반 edge 추출이 정확하고 제어 가능하며, subpixel 정밀도를 높일 수 있다.

1D based edge detection

 

- 한 줄의 intensity profile에서 경계점을 찾는 방식 (예: 특정 row 또는 column)
- Subpixel 보간, 잡음 억제 용이, 정밀도 향상, 구조 선형성 이용 가능
- Line & Space 구조, mask/wafer CD 측정, 전자현미경 이미지 등

 

예제

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

// 1D derivative 계산 후 subpixel 보간으로 edge 위치 추정
vector<float> findEdges1DWithSubpixel(const vector<float>& profile) {
    vector<float> edges;

    for (size_t i = 1; i < profile.size() - 1; ++i) {
        float prev = profile[i - 1];
        float curr = profile[i];
        float next = profile[i + 1];

        // 1차 미분 극대점 조건 (edge 후보)
        if ((curr > prev && curr > next) || (curr < prev && curr < next)) {
            // Subpixel 보간 (parabola fitting)
            float denom = prev - 2 * curr + next;
            if (fabs(denom) < 1e-5) continue; // flat or noisy

            float offset = 0.5f * (prev - next) / denom;
            edges.push_back(i + offset);
        }
    }

    return edges;
}

// 이미지에서 특정 row 기반 edge 추출
void detectEdge1D(const Mat& gray, int rowIdx) {
    vector<float> profile(gray.cols);
    for (int x = 0; x < gray.cols; ++x)
        profile[x] = static_cast<float>(gray.at<uchar>(rowIdx, x));

    // 1D 미분
    vector<float> diff(profile.size(), 0);
    for (int i = 1; i < profile.size() - 1; ++i)
        diff[i] = 0.5f * (profile[i + 1] - profile[i - 1]);

    // Subpixel edge 찾기
    vector<float> edgePositions = findEdges1DWithSubpixel(diff);

    // 출력
    cout << "1D Subpixel Edges at row " << rowIdx << ":\n";
    for (auto pos : edgePositions)
        cout << "  x = " << pos << " px" << endl;

    // 시각화
    Mat vis;
    cvtColor(gray, vis, COLOR_GRAY2BGR);
    for (float x : edgePositions)
        circle(vis, Point((int)x, rowIdx), 3, Scalar(0, 0, 255), -1);

    imshow("1D Edge Detection", vis);
    waitKey(0);
}

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

    Mat img = imread(argv[1], IMREAD_GRAYSCALE);
    if (img.empty()) {
        cerr << "Image load failed!" << endl;
        return -1;
    }

    int rowToAnalyze = img.rows / 2;  // 중간 라인
    detectEdge1D(img, rowToAnalyze);

    return 0;
}

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