Files
ant-vision-inspector/PROJECT_CONTEXT.md
2026-06-10 16:18:41 +09:00

264 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ANT 비전 검사 시스템 — 프로젝트 컨텍스트
> 최종 갱신: 2026-05-13
---
## 1. 프로젝트 구조 및 파일 목록
```
E:\ANT\
├── main.py # 엔트리포인트 (스플래시 → 백그라운드 초기화 → MainWindow)
├── logger.py # 로그 시스템 (app/inspect/timing/train CSV)
├── find_cells_trigger.py # Cognex 셀 전체 스캔 유틸 (진단용)
├── config.json # 런타임 설정 저장 (cognex/basler/db/ai/conveyor/plc)
├── camera/
│ ├── insight.py # InSightCamera — Telnet + FTP 영구세션
│ └── basler.py # BaslerCamera — pypylon SDK
├── db/
│ ├── sql_client.py # SQLClient — MS SQL Server (pyodbc, ODBC Driver 18)
│ └── mysql_client.py # MySQLClient — 미사용 레거시 (pymysql)
├── ai/
│ ├── detector.py # Detector — YOLOv8 추론 (ultralytics)
│ └── trainer.py # Trainer + TrainWorker — 재학습 (별도 subprocess)
├── logic/
│ ├── inspector.py # Inspector — PatMax 결과 판독 + 모델 판별 + Pass/Fail
│ ├── group_manager.py # GroupManager — A/B 그룹 수동 전환 (최대 4종)
│ └── pattern_matcher.py # PatternMatcher — ORB 특징점 + 엣지 NCC fallback
├── plc/
│ └── plc_client.py # PLCClient — 인터페이스만 정의 (미구현)
├── gui/
│ ├── main_window.py # MainWindow — 4탭 네비게이션, 상태바
│ ├── splash_screen.py # SplashScreen + InitWorker
│ ├── image_settings_dialog.py # 이미지 설정 다이얼로그
│ └── pages/
│ ├── settings_page.py # 환경설정 탭 (연결카드 + 관리자 설정 다이얼로그)
│ ├── register_page.py # 제품 등록 탭 (MES 불러오기 + 캡처)
│ ├── inspect_page.py # 검사 탭 (파이프라인 워커 + 결과 표시)
│ └── retrain_page.py # 재학습 탭 (YOLOv8 재학습 UI)
├── assets/
│ ├── images/ant_logo.png
│ └── patterns.pkl # PatternMatcher 등록 패턴 저장 파일
└── logs/
├── app/YYYY-MM-DD.log # 전체 앱 로그 (print 가로채기)
├── inspect/YYYY-MM-DD.csv # 검사 결과 CSV
└── timing/YYYY-MM-DD.csv # Cognex/Basler 타이밍 CSV
```
---
## 2. 확정된 셀 주소 (Cognex GV 방식)
`logic/inspector.py` `PATTERN_RESULT_CELLS` 딕셔너리에 확정:
| 셀 주소 | ID | 제품명 | 모델 | Type |
|---------|-----|--------|------|------|
| **A27** | 1 | LOW REF | LX3 | RH |
| **A77** | 2 | LOW REF | LX3 | LH |
| **A127** | 3 | LOW REF NAS | LX3 | RH |
| **A177** | 4 | LOW REF NAS | LX3 | LH |
- 읽기 방식: `GV{셀주소}` 전송 → 응답 `"1"` + 값 라인 수신
- 값 파싱: `"(736.1,742.0) -1.8 = 82.9"` 형식에서 `=` 뒤 점수 추출
- `#ERR` 포함 시 → matched=False, score=0.0
> Cognex 인식 외 추가 제품은 `PatternMatcher` (Python ORB/NCC) 경로로 처리
---
## 3. DB 접속 정보
**드라이버**: `ODBC Driver 18 for SQL Server` (pyodbc)
**연결 문자열 구조** (`db/sql_client.py`):
```
DRIVER={ODBC Driver 18 for SQL Server};
SERVER=<서버주소,포트>;
DATABASE=<DB명>;
UID=<사용자명>;
PWD=<비밀번호>;
TrustServerCertificate=yes;
Encrypt=optional;
```
**설정 UI 예시 서버 주소**: `Wizis.iptime.org,20220`
**사용 뷰/테이블**:
- `vi_AI_mt_Article` — 제품 등록 탭에서 리플렉터 목록 조회
```sql
SELECT ArticleID, Article, BuyerArticleNo
FROM vi_AI_mt_Article
WHERE Article LIKE '%REF%'
ORDER BY ArticleID
```
**설정 저장 위치**: `config.json` → `"db"` 키 (server/database/username/password)
**자동 연결**: 앱 시작 시 `MainWindow._auto_connect_db()` 가 config.json 값으로 자동 시도
---
## 4. 구현 완료된 기능
### 카메라
- [x] Cognex In-Sight — Telnet 로그인 (admin/빈 비밀번호)
- [x] Cognex In-Sight — FTP 영구세션 (NOOP keepalive + 자동 재연결)
- [x] Cognex In-Sight — SE8 소프트웨어 트리거
- [x] Cognex In-Sight — FTP BMP 우선 / JPG fallback 이미지 수신
- [x] Basler USB — pypylon GrabOne 단일 캡처
- [x] Basler USB — ExposureAuto=Continuous 연결
- [x] Basler USB — 연속 grab (start_continuous / grab_latest)
### 검사 로직
- [x] Cognex GV 방식 PatMax 결과 조회 (A27/A77/A127/A177)
- [x] Python PatternMatcher — ORB 특징점 매칭 (Lowe's ratio test 0.75)
- [x] Python PatternMatcher — 엣지 NCC fallback (특징점 10개 미만 시)
- [x] PatternMatcher — ORB+NCC 혼합 결과 병합
- [x] 모델 판별 (최고 점수 패턴 선택 → 허용 그룹 여부 확인)
- [x] Pass/Fail 최종 판정 (cognex_pass AND basler_pass)
- [x] 그룹 A/B 수동 전환 (최대 4종 per 그룹)
### 검사 파이프라인 (InspectWorker)
- [x] Cognex 트리거 → 1초 대기 → FTP 수신 → PatMax 병렬 처리 (서브스레드)
- [x] Basler 캡처 — 트리거 기준 belt_delay 후 촬영 (동시 진행)
- [x] YOLOv8 추론 — 불량 감지 (confidence ≥ 0.5)
- [x] 검사 결과 카운터 — 그룹별 전체/양품/불량/미인식
### AI
- [x] YOLOv8 모델 로드/해제 (지연 로딩 — torch DLL 충돌 방지)
- [x] 4클래스 추론: 스크래치/이물/흑점/변형
- [x] 재학습 — 데이터셋 준비 (80/20 train/val 자동 분할)
- [x] 재학습 — YOLOv8n 기반, 별도 subprocess 격리 (Qt 충돌 방지)
- [x] 재학습 — 에포크별 진행 콜백 → UI ProgressBar 연동
### GUI
- [x] 1920×1080 전체화면, 다크 테마
- [x] ChevronTabButton — breadcrumb 스타일 4탭 (환경설정/제품 등록/검사/재학습)
- [x] 재학습 탭 더블클릭(600ms) → 창 최소화 단축
- [x] 환경설정 탭 — 연결 카드 (코그넥스/Basler/DB/AI)
- [x] 관리자 설정 다이얼로그 — 6탭 (코그넥스/Basler/DB/AI모델/컨베이어/PLC)
- [x] 관리자 인증 — 4자리 PIN 키패드 (기본값: 1234)
- [x] 제품 등록 탭 — MES 불러오기 (DB 연결 시 활성화)
- [x] 제품 등록 탭 — In-Sight 트리거 캡처 + 미리보기
- [x] 검사 탭 — Cognex/Basler 듀얼 영상 표시
- [x] 검사 탭 — Basler 이미지에 불량 BBox 오버레이 (클래스별 색상)
- [x] 상태바 — 코그넥스/Basler/DB 연결 상태 실시간 표시
- [x] 컨베이어 딜레이 설정 — 거리(cm) ÷ 속도(cm/s) 자동 계산
### 로그
- [x] print 가로채기 — 타임스탬프 자동 prefix + 파일 저장
- [x] 세션 시작/종료 헤더 (비정상 종료 감지 포함)
- [x] 검사 결과 CSV (`logs/inspect/`)
- [x] 카메라 타이밍 CSV (`logs/timing/`)
- [x] 사용자 액션 강조 로그
---
## 5. 미구현 / 블로킹 기능
### 블로킹 (핵심 미완성)
| 항목 | 파일 | 상태 |
|------|------|------|
| 검사 결과 DB 저장 | `db/sql_client.py:save_inspection_result()` | TODO — 저장 테이블 미확정 |
| PatternMatcher 등록 UI 연동 | `gui/pages/register_page.py` | 캡처만 구현, `matcher.train()` 호출 없음 |
| PatternMatcher 등록 저장 버튼 | `gui/pages/register_page.py` | 미구현 |
### 미구현 (인터페이스만 정의)
| 항목 | 파일 | 상태 |
|------|------|------|
| PLC 통신 전체 | `plc/plc_client.py` | 통신 방식 미확정 (Modbus TCP / MC프로토콜 / OPC-UA 중 선택 필요) |
| PLC 연결 버튼 | `gui/pages/settings_page.py:_build_tab_plc()` | print만 출력 |
| DB 리플렉터 등록/갱신 | `db/mysql_client.py:save_reflector()` | `pass` |
| 재학습 후 모델 자동 교체 | `gui/pages/retrain_page.py` | 미확인 |
### 부분 구현
| 항목 | 상태 |
|------|------|
| Basler 노출/게인 설정 | UI만 있음, 연결 후 `ExposureAuto=Continuous` 고정 |
| 제품 등록 탭 RH/LH 방향 표시 | DB `type` 필드가 비어있어 화살표 미표시 |
---
## 6. 시스템 흐름 요약
### 앱 시작
```
main.py
└─ SplashScreen + InitWorker (백그라운드)
├─ InSightCamera.connect() → Telnet + FTP 세션
├─ BaslerCamera.connect() → pypylon
├─ config.json 로드
└─ MainWindow(insight, basler, config)
├─ PatternMatcher.load() → assets/patterns.pkl
├─ SQLClient 자동 연결 → config.json db 설정
└─ Detector (모델 미로드 상태)
```
### 검사 1사이클 (InspectWorker.run)
```
[메인 루프]
├─ [Cognex 서브스레드] ─────────────────────────────────────┐
│ SE8 트리거 전송 │
│ → sleep(1.0) │
│ → FTP get_image() (BMP/JPG) │
│ → cognex_image_ready.emit(raw) ← GUI 표시 │
│ → inspector.read_patmax_results() ← GV 셀 조회 │
│ → inspector.match_image() ← Python ORB/NCC │
│ → cognex_out["results"] 저장 │
│ │
├─ [워커 메인] belt_delay 대기 후 │
│ Basler.capture() │
│ → detector.detect() ← YOLOv8 추론 │
│ → basler_image_ready.emit(frame, detections) ← GUI │
│ │
├─ ct.join(timeout=10.0) ← Cognex 서브스레드 완료 대기 ───┘
├─ inspector.identify_model(results, allowed_ids)
│ → 최고 점수 패턴 선택 → 허용 그룹 여부 확인
├─ inspector.judge(cognex_pass, basler_pass)
│ → "PASS" or "FAIL"
└─ result_ready.emit(dict) → UI 카운터/결과 표시 + CSV 기록
```
### 모델 판별 우선순위
1. **Cognex GV 셀** (A27/A77/A127/A177) — job 파일 내 PatMax 결과
2. **Python PatternMatcher** (ORB 특징점 → NCC fallback) — 추가 등록 제품
두 결과를 병합하여 가장 높은 점수의 패턴을 최종 선택.
### 컨베이어 딜레이 계산
```
belt_delay (초) = 카메라 간 거리(cm) ÷ 벨트 속도(cm/s)
기본값: 100cm ÷ 30cm/s = 3.33초
```
### 설정 저장
- 모든 설정은 `config.json` (프로젝트 루트)에 JSON으로 저장
- 앱 재시작 시 자동 로드 및 카메라/DB 자동 연결 시도
---
## 7. 주요 의존성
| 패키지 | 용도 |
|--------|------|
| PyQt5 | GUI 프레임워크 |
| pypylon | Basler 카메라 SDK |
| ultralytics | YOLOv8 추론/학습 |
| opencv-python | 이미지 처리, ORB, NCC |
| pyodbc | MS SQL Server 연결 |
| pymysql | MySQL (레거시, 미사용) |
| numpy | 배열 처리 |
| pyyaml | 학습 데이터셋 yaml 생성 |