1카메라와 조명 시스템
비전 AI의 성능은 하드웨어에서 시작됩니다. 카메라와 조명 선택이 결함 검출 성능의 80%를 좌우한다고 해도 과언이 아닙니다.
카메라 유형별 비교:
| 유형 | 특징 | 적용 분야 | 해상도 |
| 에어리어 스캔 | 2D 센서, 순간 촬영 | 정지 검사, 로봇 가이드 | 1-60MP |
| 라인 스캔 | 1D 센서, 연속 이동 촬영 | 웹 검사, 컨베이어 | 2K-16K |
| 3D 카메라 | 깊이 정보 포함 | 덴트, 갭/단차 측정 | 1-5MP |
| 열화상 | 온도 분포 영상 | 발열 이상, 용접 품질 | 320×240~640×480 |
해상도 계산 가이드
필요 해상도 계산
최소 결함 크기: 0.1mm
FOV (Field of View): 100mm x 100mm
결함당 최소 픽셀: 3-5 픽셀
필요 해상도 = FOV / (결함 크기 / 픽셀 수)
= 100mm / (0.1mm / 5 pixels)
= 5000 pixels
5MP 카메라 (2448 x 2048) 이상 필요
조명 선택 가이드
• 스크래치, 미세 흠 → 로우 앵글 (측면 조명)
• 먼지, 이물질 → 백라이트 (투과 조명)
• 균일한 표면 → 돔 라이트 (확산 조명)
• 3D 형상 → 구조광 (패턴 조명)
• 반사 표면 → 편광 필터 + 돔 라이트
2이미지 전처리 파이프라인
원본 이미지를 AI 모델에 입력하기 전에 품질을 개선하고 정규화하는 과정입니다.
import cv2
import numpy as np
from typing import Tuple
class ImagePreprocessor:
"""제조 비전 이미지 전처리"""
def __init__(self, target_size: Tuple[int, int] = (224, 224)):
self.target_size = target_size
def preprocess(self, image: np.ndarray) -> np.ndarray:
"""전처리 파이프라인 실행"""
# 1. 노이즈 제거
image = cv2.GaussianBlur(image, (3, 3), 0)
# 2. 히스토그램 평활화 (대비 개선)
if len(image.shape) == 3:
lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)
lab[:,:,0] = cv2.createCLAHE(clipLimit=2.0).apply(lab[:,:,0])
image = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)
# 3. 정규화
image = image.astype(np.float32) / 255.0
# 4. 리사이즈
image = cv2.resize(image, self.target_size)
return image
def align_roi(self, image: np.ndarray, template: np.ndarray) -> np.ndarray:
"""템플릿 매칭으로 ROI 정렬"""
result = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
_, _, _, max_loc = cv2.minMaxLoc(result)
h, w = template.shape[:2]
roi = image[max_loc[1]:max_loc[1]+h, max_loc[0]:max_loc[0]+w]
return roi
1 노이즈 제거
Gaussian Blur, Median Filter로 센서 노이즈 제거. 에지 보존 필터(Bilateral) 선택적 사용
2 대비 개선
CLAHE(적응 히스토그램 평활화)로 조명 불균일 보정. 결함 가시성 향상
3 ROI 추출
검사 대상 영역만 잘라내기. 템플릿 매칭 또는 딥러닝 검출기 활용
4 정규화
픽셀값 0-1 스케일링. ImageNet 평균/표준편차로 정규화 (Transfer Learning시)
3데이터 증강 (Augmentation)
학습 데이터를 인위적으로 늘려 모델의 일반화 성능을 향상시킵니다. 제조 환경의 변동(조명, 위치, 각도)을 시뮬레이션합니다.
import albumentations as A
from albumentations.pytorch import ToTensorV2
# 학습용 증강 (강한 증강)
train_transform = A.Compose([
A.Resize(224, 224),
A.HorizontalFlip(p=0.5),
A.VerticalFlip(p=0.5),
A.RandomRotate90(p=0.5),
A.ShiftScaleRotate(shift_limit=0.1, scale_limit=0.2, rotate_limit=45, p=0.5),
# 조명 변동 시뮬레이션
A.RandomBrightnessContrast(brightness_limit=0.3, contrast_limit=0.3, p=0.5),
A.RandomGamma(gamma_limit=(80, 120), p=0.3),
A.GaussNoise(var_limit=(10, 50), p=0.3),
# 블러 (초점 불량 시뮬레이션)
A.OneOf([
A.MotionBlur(blur_limit=5),
A.GaussianBlur(blur_limit=5),
], p=0.3),
A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
ToTensorV2(),
])
# 검증/추론용 (증강 없음)
val_transform = A.Compose([
A.Resize(224, 224),
A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
ToTensorV2(),
])
증강 주의사항: 결함의 특성이 손상되지 않도록 증강을 설계해야 합니다. 예: 스크래치의 방향이 중요하면 90도 회전은 피함. 색상 결함 검사에서는 색상 변환 증강 제외.
4라벨링 도구와 전략
고품질 라벨링은 AI 모델 성능의 핵심입니다. 제조 결함 라벨링에 적합한 도구와 전략을 소개합니다.
주요 라벨링 도구:
| 도구 | 유형 | 특징 | 라이선스 |
| CVAT | 웹 기반 | 다양한 어노테이션, 팀 협업, AI 보조 | 오픈소스 |
| Label Studio | 웹 기반 | ML 통합, 다양한 데이터 타입 | 오픈소스 |
| Roboflow | SaaS | 자동 증강, 데이터셋 버전 관리 | 상용 |
| Labelbox | SaaS | 엔터프라이즈급, 워크플로우 관리 | 상용 |
라벨링 가이드라인 예시 (결함 분류)
결함 클래스 정의
OK: 정상 제품, 결함 없음
Scratch: 표면 긁힘, 길이 0.5mm 이상
세부: Light Scratch, Deep Scratch
Dent: 표면 찍힘, 면적 1mm² 이상
Stain: 오염, 변색, 이물질
세부: Oil Stain, Water Mark, Foreign Material
Crack: 균열, 깨짐
1. 경계 사례 기준
Scratch 길이 0.3~0.5mm → 'Light Scratch' 또는 'OK'
여러 결함 중첩 → 가장 심각한 결함으로 분류
2. 품질 검증
전문가 2인 이상 교차 검증
불일치율 10% 이상 → 가이드라인 수정
3. 주기적 리뷰
월 1회 라벨링 일관성 감사
신규 결함 유형 발견 시 클래스 추가
5데이터셋 구조와 관리
체계적인 데이터셋 관리는 모델 재현성과 버전 관리에 필수적입니다.
권장 디렉토리 구조
defect_dataset/
raw/ # 원본 이미지
2024-01-15/ (line_A/, line_B/)
2024-01-16/
processed/ # 전처리된 이미지
train/ (OK/, Scratch/, Dent/, Stain/, Crack/)
val/, test/
annotations/ # 라벨 데이터
train.json, val.json (COCO 포맷)
metadata/
class_mapping.json, split_info.json, statistics.json
README.md # 데이터셋 설명서
메타데이터 예시 (statistics.json)
{
"version": "1.2.0",
"created_at": "2024-01-20",
"total_samples": 15000,
"class_distribution": {
"OK": 12000,
"Scratch": 1500,
"Dent": 800,
"Stain": 500,
"Crack": 200
},
"split_ratio": {"train": 0.7, "val": 0.15, "test": 0.15}
}
버전 관리: DVC(Data Version Control) 또는 MLflow를 사용하여 데이터셋 버전을 추적하세요. 모델 학습 시 어떤 버전의 데이터로 학습했는지 기록이 필수입니다.
6품질 검증과 데이터 정제
학습 전 데이터 품질을 검증하고 문제가 있는 샘플을 정제하는 과정입니다.
import os
import hashlib
from PIL import Image
from collections import Counter
class DatasetValidator:
"""데이터셋 품질 검증"""
def validate(self, data_dir: str) -> dict:
"""데이터셋 검증 실행"""
issues = {
'corrupted': [],
'duplicates': [],
'size_outliers': [],
'class_imbalance': None
}
hashes = {}
sizes = []
labels = []
for root, dirs, files in os.walk(data_dir):
for file in files:
if not file.lower().endswith(('.jpg', '.png', '.bmp')):
continue
path = os.path.join(root, file)
label = os.path.basename(root)
labels.append(label)
# 1. 손상된 이미지 검사
try:
img = Image.open(path)
img.verify()
img = Image.open(path)
sizes.append(img.size)
except:
issues['corrupted'].append(path)
continue
# 2. 중복 이미지 검사
with open(path, 'rb') as f:
file_hash = hashlib.md5(f.read()).hexdigest()
if file_hash in hashes:
issues['duplicates'].append((path, hashes[file_hash]))
else:
hashes[file_hash] = path
# 3. 크기 이상치 검사
avg_size = np.mean([s[0]*s[1] for s in sizes])
for i, size in enumerate(sizes):
if size[0]*size[1] < avg_size * 0.5:
issues['size_outliers'].append(i)
# 4. 클래스 불균형 검사
class_counts = Counter(labels)
issues['class_imbalance'] = dict(class_counts)
return issues
# 사용 예시
validator = DatasetValidator()
issues = validator.validate('defect_dataset/processed/train')
print(f"손상 이미지: {len(issues['corrupted'])}개")
print(f"중복 이미지: {len(issues['duplicates'])}개")
print(f"클래스 분포: {issues['class_imbalance']}")