# 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 생성 |
