유리 / 투명 플라스틱 융합 분류기
YOLO 검출 결과와 AS7265x 근적외 분광(18채널)을 결합해 유리와 투명 플라스틱(PET) 을 구분한다. 재활용 선별 컨베이어에서 수집한 데이터로 학습했다.
YOLO 26클래스 점수 ──► z_rgb (2) ──┐
├─► concat(4) ─► MLP ─► softmax ─► 유리 / 투명 플라스틱
NIR 18ch ─► SpectralEncoder ─► z_n ┘ × gate
학습 파라미터는 3,669개(인코더 3,554 + 헤드 114 + 게이트 1)로 매우 작다. YOLO 백본은 포함하지 않으며 그 출력만 입력으로 받는다.
사용법
from predict import FusionPredictor
p = FusionPredictor()
r = p.predict(nir=[...18개...], yolo_class="페트병", yolo_conf=0.926)
print(r["label"]) # '유리' 또는 '투명 플라스틱'
26차원 점수 벡터로도 넣을 수 있다.
r = p.predict(nir=[...], yolo_scores=[0, 0, ..., 0.96, 0])
동작 확인:
python selftest.py
입력
yolo_scores |
26차원 클래스별 confidence. 또는 yolo_class(id/한글이름) + yolo_conf |
nir |
AS7265x 18채널. 파장 오름차순이 기본. CSV 컬럼 순서면 nir_order="csv" |
파장 오름차순: A410 B435 C460 D485 E510 F535 G560 H585 R610 I645 S680 J705 T730 U760 V810 W860 K900 L940
분광값은 행 합이 1이 되도록 정규화된 값을 전제한다.
출력
{"label": "투명 플라스틱", "confidence": 0.802,
"prob": {"유리": 0.198, "투명 플라스틱": 0.802},
"z_rgb": {...}, "z_n": [...], "gate": 0.0551,
"yolo_class": "페트병", "yolo_in_scope": True}
yolo_in_scope=False 는 YOLO 가 유리/PET 어느 쪽으로도 확정하지 못한 경우로,
NIR 만으로 판정한 것이다.
성능
교차검증(RepeatedStratifiedKFold 5x10), 52쌍, 다수클래스 baseline 0.558.
| 구간 | 정확도 |
|---|---|
| YOLO 가 유리/PET 로 확정한 46건 | 0.957 |
| YOLO 무검출 등 6건 | 0.667 |
| 전체 52건 | 0.923 |
NIR 단독(신규 93행, 중첩 교차검증): 0.693 (baseline 0.516, SNV → PCA12 → SVM)
적용 범위
유리병(소주병·맥주병·박카스병 등)과 투명 플라스틱(PET 병, 일회용 음료수잔)을 대상으로 한다.
스티로폼·봉지·밀폐용기 등 PET 가 아닌 플라스틱은 대상이 아니며 yolo_in_scope=False 로 걸러진다.
분광 표준화 통계는 수집 환경에 의존하므로, 다른 리그에서는 해당 환경의 통계를 다시 구해야 한다.
센서
AS7265x 트라이어드 분광 센서(SparkFun). 410~940nm, 18채널, FWHM 20nm. PET 식별의 주요 흡수대(1차 배음 ~1660nm)에는 도달하지 못하며 3차 배음 영역만 걸친다. 같은 센서로 폐플라스틱 6종을 72.5% 로 분류한 선행 연구가 있다 (Sensors, MDPI).
파일
predict.py 추론 API
model.py 신경망 정의
fusion_model.pt 가중치 + 표준화 통계 + 클래스 매핑
selftest.py 자체 점검
testdata/ 샘플 2개 (유리 1, 투명 플라스틱 1) + 기대 출력
_retrain/ 재학습 코드 (원본 데이터 별도 필요)
_docs/ 구축 경과 기록
라이선스
AGPL-3.0. 상위 YOLO 모델(do1ng/few_shot)이 Ultralytics AGPL-3.0 기반이므로 이를 따른다.