머신비전과 엣지 AI — 물리적 실증부터 시스템 구현까지
1. 시작하는 관점 — “잘 된다”는 착각을 경계한다
현장의 머신비전 시스템은 알고리즘만으로 완성되지 않는다.
이차전지 전극 제조와 같은 고속 롤투롤(Roll-to-Roll) 연속 공정을 예로 들어보자. 라인 속도 60 m/min(= 1,000 mm/s)으로 주행하는 웹(Web) 표면에서 폭 0.05 mm급 스크래치를 검출해야 한다면, 소프트웨어를 논하기 전에 다음 세 가지 물리량이 먼저 확보되어야 한다.
| 물리량 | 요구 조건 예시 | 미확보 시 결과 |
|---|---|---|
| 광학 분해능 (mm/px) | 결함 폭의 1/3 이하 → 0.017 mm/px 이하 | 결함이 픽셀 사이에 묻혀 소실 |
| 노출 중 이동량 (mm) | 분해능의 1/2 이하 → 노출시간 8 µs 이하 | 모션 블러로 엣지 정보 붕괴 |
| 피사계심도 DOF (mm) | 웹 플러터(±0.5 mm) 이상 | 주기적 초점 이탈 → 오검출 폭증 |
이 세 가지 중 하나라도 무너진 상태에서 딥러닝 모델의 하이퍼파라미터를 아무리 조정해도, 그것은 존재하지 않는 정보를 복원하려는 시도일 뿐이다. 현장에서 마주하는 검사 시스템 실패의 대부분은 렌즈의 분해능, 조명의 파장, 피사계심도의 물리적 한계를 무시한 채 소프트웨어로 보정하려는 데서 비롯된다.
녹트비전(NoctVision)은 광학이라는 ‘물리’에서 출발하여, Jetson과 같은 엣지 디바이스에서 실제로 돌아가는 ‘검사 시스템’을 구현하는 전 과정을 실증적으로 기록하기 위해 개설되었다.
2. 첫 포부 — 이 블로그가 도달하려는 지점
세 부류의 독자에게 각각 하나씩을 약속한다.
- 비전검사 개발자에게: 렌즈 선정표를 카탈로그 감(感)이 아니라 수식으로 뽑아내는 방법. FOV·WD·센서 크기·픽셀 분해능에서 초점거리와 F값이 유도되는 전 과정을 계산 코드와 함께 제공한다.
- 엣지 AI 입문자에게: “PC에서는 됐는데 보드에서는 안 되는” 상황의 정량적 해부. Jetson Orin 계열에서 ONNX → TensorRT 변환, INT8 양자화, 전처리 파이프라인 병목까지 FPS 수치로 추적한다.
- 광학을 제대로 알고 싶은 엔지니어에게: MTF, 회절 한계, 텔레센트릭 렌즈의 존재 이유 같은 주제를 “외우는 지식”이 아니라 “계산 가능한 물리”로 다룬다.
최종 목표는 하나다. 독자가 이 블로그의 글만으로 자신의 검사 대상에 맞는 광학계를 계산하고, 엣지 보드 위에서 측정 가능한 성능으로 재현하는 것.
3. 블로그 운영 정책
추상적인 개념 서술이나 근거 없는 “잘 된다” 식의 포스팅은 전면 배제한다. 모든 글은 코드와 측정 결과로 증명하며, 다음 3원칙을 따른다.
- 제1원칙 — 광학은 물리다. 시스템 설계의 첫 단추는 렌즈와 조명이다. 모든 광학 설계는 초점거리(f), 조리개 값(F/#), 피사계심도(DOF), MTF 등의 명확한 물리량과 수식으로 검증한다. 단위는 mm로 통일한다.
- 제2원칙 — 실증적 코드만 게시한다. 동작이 미검증된 코드는 업로드하지 않는다. 모든 Python/C++ 코드에는 핵심 로직과 연계된 물리 수식 주석을 필수로 포함하여 재현성을 보장한다.
- 제3원칙 — 엣지 환경의 정량 지표를 제시한다. PC의 무제한 리소스가 아닌 엣지 보드 구동을 전제로 한다. 최종 결과물은 항상 처리 속도(FPS), 검사 해상도(mm/px), 정확도(mAP, F1)로 제시한다.
4. 포스팅 표준 구조
앞으로 발행되는 모든 기술 포스팅은 일관된 정보 전달을 위해 아래 5단계 템플릿을 준수한다.
- 풀려는 문제 — 무엇을 검출/측정하는가 (대상물 재질, 주행 속도, 결함의 종류와 최소 크기)
- 광학 설계 — 타겟 분해능 도출, 렌즈·조명·작동거리(WD) 계산
- 알고리즘/모델 — 비전 검사 알고리즘 구조와 핵심 코드 (이론적 배경 포함)
- 엣지 구동 — 대상 보드(Jetson 등)에서의 모델 최적화(TensorRT 등)와 파이프라인 구축
- 결과 및 한계 — 최종 FPS·정확도 데이터와 전체 재현 코드
5. [Preview] 광학과 코드의 결합 — 녹트비전의 방식
녹트비전이 지향하는 ‘물리와 코드의 결합’을 미리 보인다. 검사 시스템 설계의 출발점인 초점거리와 픽셀 분해능 계산이다.
수식 (단위: 전부 mm)
작동거리 WD, 센서 크기 h, 요구 시야 FOV가 주어졌을 때 필요한 초점거리 f는 얇은 렌즈 근사에서 다음과 같다.
f = (h × WD) / (FOV + h)
이때 픽셀 분해능은 FOV를 센서 픽셀 수 N으로 나눈 값이다.
Resolution = FOV / N [mm/px]
검증된 계산 코드
import numpy as np
def calculate_focal_length(sensor_size_mm: float, wd_mm: float, fov_mm: float) -> float:
"""
광학 렌즈의 초점거리(Focal Length)를 계산한다.
Formula: f = (h * WD) / (FOV + h) [모든 단위 mm]
- h : sensor_size_mm (센서 유효 폭)
- WD : wd_mm (Working Distance, 렌즈-대상 거리)
- FOV : fov_mm (Field of View, 요구 시야 폭)
"""
# 분모가 0 이하가 되는 물리적으로 무의미한 입력 차단
if fov_mm + sensor_size_mm <= 0:
raise ValueError("FOV와 센서 크기의 합은 0보다 커야 합니다.")
focal_length = (sensor_size_mm * wd_mm) / (fov_mm + sensor_size_mm)
return round(focal_length, 2)
def calculate_pixel_resolution(fov_mm: float, sensor_pixels: int) -> float:
"""
픽셀 분해능(mm/px)을 계산한다.
Formula: Resolution = FOV / N [mm/px]
- FOV : fov_mm (시야 폭, mm)
- N : sensor_pixels (해당 방향 픽셀 수)
"""
if sensor_pixels <= 0:
raise ValueError("픽셀 수는 1 이상이어야 합니다.")
return round(fov_mm / sensor_pixels, 4)
# [실증 데이터]
# 조건: 1/2인치 센서(가로 유효폭 6.4 mm), WD 200 mm, 요구 FOV 100 mm, 가로 2448 px
f_req = calculate_focal_length(sensor_size_mm=6.4, wd_mm=200.0, fov_mm=100.0)
res = calculate_pixel_resolution(fov_mm=100.0, sensor_pixels=2448)
print(f"Required Focal Length : {f_req} mm") # 출력: 12.03 mm
print(f"Pixel Resolution : {res} mm/px") # 출력: 0.0408 mm/px (≈ 40.8 µm/px)
계산 결과 해석
| 항목 | 값 | 판정 |
|---|---|---|
| 필요 초점거리 f | 12.03 mm | 12 mm 표준 렌즈 선정 후 WD 미세 조정 |
| 픽셀 분해능 | 0.0408 mm/px | 폭 0.12 mm 이상 결함의 3px 룰 충족 |
| 폭 0.05 mm 결함 검출 | 1.2 px 수준 | 불충족 → FOV 축소 또는 고해상 센서 필요 |
이것이 녹트비전의 방식이다. “이 렌즈로 될까?”라는 질문에 느낌이 아닌 mm 단위 수치로 답하고, 안 되는 것은 안 된다고 계산으로 밝힌다.
6. 예정된 첫 시리즈
- 광학 기초 계산 시리즈: 초점거리·F값·DOF·MTF를 Python 계산기로 만들기
- 라인스캔 vs 에어리어 카메라: 고속 웹 검사에서의 선택 기준 (노출시간·인코더 동기 계산 포함)
- Jetson Orin Nano 표면 결함 검출: Anomalib/YOLOv8 → TensorRT 파이프라인, FPS 실측
허상이 아닌, 현장에서 즉시 적용 가능한 실증적 머신비전 시스템 구축의 기록을 시작한다.
Hi, this is a comment.
To get started with moderating, editing, and deleting comments, please visit the Comments screen in the dashboard.
Commenter avatars come from Gravatar.