웨이퍼나 PCB 검사 프로젝트를 진행하다 보면 동일한 패턴이 반복되는 이미지를 자주 다루게 된다. 이러한 이미지에서 미세 결함(Defect)을 검출하기 위해서는, 강한 에지 성분을 가진 반복 패턴을 먼저 제거(Pattern Removal)해야 한다.
패턴 제거를 위해 FFT 필터링이나 마스터 이미지와의 Subtraction 방식을 고려하고 있는데, 이를 위해서는 선행적으로 각 디펙트의 인덱싱정보를 위해 각 패턴의 정확한 중심 좌표(Center Position)를 확보해야 한다.
본 포스팅에서는 2D 이미지 프로세싱 부하를 줄이기 위해 투영(Projection) 기법을 활용하여 Grid Pattern의 중심을 검출하는 로직(GridPatternMatching) 구현 과정을 정리한다.
1. 검증 환경 구성
실제 현장에서 다루는 검사 시료(Sample)는 고객사의 공정 노하우가 포함된 대외비(Confidential) 자료이므로 본 포스팅에 공개할 수 없다.
따라서 실제 시료와 유사한 환경을 가정하되, 보안 이슈를 피하고 알고리즘의 순수 로직(Logic) 검증에 집중하기 위해 가상의 테스트 이미지를 생성하여 검증을 진행했다.
- 테스트 이미지: BGA(Ball Grid Array) 스타일의 10x10 격자 패턴
- 해상도: 1024x1024
- 목표: 100개 원형 패턴의 중심 좌표를 Sub-pixel 단위로 검출

2. 접근 방식: Projection (차원 축소)
수많은 패턴을 개별 Blob으로 인식하여 처리하는 것은 연산 비용 측면에서 비효율적이다. 패턴이 격자(Grid) 형태로 정렬되어 있다는 특성을 활용하여, 2차원 이미지를 가로/세로 방향으로 각각 투영(Projection)하여 1차원 데이터로 변환하는 방식을 택했다.
OpenCV의 reduce 함수를 사용하면 간단하게 구현 가능하다.
// [Code Fragment] Projection 데이터 추출
std::vector<float> CGridPatternMatching::GetProjection(const cv::Mat& img, bool bIsRow)
{
cv::Mat sumMat;
// 행(Row) 또는 열(Col) 방향으로 픽셀 강도를 누적 합산 (Sum)
cv::reduce(img, sumMat, bIsRow ? 1 : 0, cv::REDUCE_SUM, CV_32F);
// Mat 형태를 vector로 변환하여 반환
// ...
}
3. 신호 분석 및 Peak 검출
추출된 1차원 Projection 데이터를 그래프로 시각화하면 아래와 같이 패턴이 존재하는 구간에서 신호값이 상승하는 것을 확인할 수 있다.
이 그래프에서 패턴의 중심을 찾기 위해 다음과 같은 로직을 적용했다.
- 데이터의 평균값을 기준으로 임계값(Threshold) 설정
- 임계값을 초과하는 구간의 시작점(Start)과 끝점(End) 인덱스 검출
- 해당 구간의 중간값((Start + End) / 2)을 패턴의 중심(Peak)으로 정의
단순히 최댓값(Max)을 찾는 것보다, 패턴의 크기(Width)를 고려하여 중심을 잡는 것이 더 안정적이다.

4. 결과 검증 (Grid Fitting)
X축 방향의 Peak와 Y축 방향의 Peak를 조합하여 최종적으로 격자(Grid) 좌표를 산출했다. 검출된 좌표의 정확성을 확인하기 위해 원본 이미지에 Crossline을 오버레이 하여 확인했다.
- Red Line: X축 중심 좌표
- Blue Line: Y축 중심 좌표
확대 확인 결과, 교차점이 각 원형 패턴의 중심과 일치함을 확인했다.

5. 정리
이상적인 환경(BGA 테스트 이미지)에서 Projection 기반의 Grid Center 검출 로직이 정상 동작함을 확인했다.
실제 구현된 클래스(CGridPatternMatching)에는 현장 적용을 위해 다음과 같은 기능들이 추가되어 있다.
- Adaptive Threshold: 조명 불균일 대응
- Master Grid Fitting: 렌즈 왜곡 등을 고려하여, 학습된(Train) 마스터 패턴의 간격 정보를 기반으로 검출된 Peak를 보정하는 로직
인덱싱에 사용될 대략적인 위치만 필요하기에 정확도는 고려 하지 않았다.
확보된 좌표 정보를 바탕으로 추후 FFT 주파수 제거 혹은 Reference Image Subtraction 작업을 수행하여 결함 검출 단계로 넘어갈 예정이다.
혹시 필요 할지 몰라 테스트 했던 Consol 프로젝트도 첨부한다.
'Vision & Inspection' 카테고리의 다른 글
| [C++/CUDA] 90GB 대용량 버퍼풀에서 4,000개 ROI만 쏙 뽑아 초고속 어파인 변환하기 (Zero-Copy & Batch Assembly) (0) | 2025.12.07 |
|---|---|
| [Insight] 이미지를 돌릴까, 마스크를 돌릴까? (Image vs Mask Rotation) (0) | 2025.12.07 |