Persistent Homology + Color Histogram으로 학습 없이 상품을 식별한다.
사진 한 장으로 위상적 지문(54D)과 색상 분포(96D)를 추출하고, 0.7초 만에 결과를 반환한다.
이미지를 grayscale 함수로 보고, 밝기 임계값을 0→255로 올리면서 나타나고(birth) 사라지는(death) 위상적 특징을 추적한다. PH는 형태를, Color는 색상을, OCR은 텍스트를 보기 때문에 세 관점이 상호 보완된다.
목적: 상품 DB 구축 (~8초/장, 정확도 우선)
1. 사진 촬영 → center_crop (3:4)
2. 원본 해상도 OCR (Tesseract eng+kor)
3. 128×128 → PH 54D + Color 96D
4. DB 저장 (150D 벡터 + OCR 텍스트)
목적: 실시간 식별 (~0.7초, 속도 우선)
1. 카메라 프리뷰 캡처
2. center_crop → OCR → 128×128
3. PH 54D + Color 96D 추출
4. Z-score 정규화 (DB 통계 기준)
5. L2 거리 − OCR 보너스 → Top-1
1. Sublevel set (원본 grayscale)
2. Edge / Sobel (경계선 강도)
3. Gradient / Laplacian (변화율)
각 filtration에서 H₀, H₁의 count, sum, max, mean, std + 4-bin 분포
H (Hue) 32 bins — 색상
S (Saturation) 32 bins — 채도
V (Value) 32 bins — 명도
각 채널 독립 히스토그램, L1 정규화
Android 앱의 MediaProjection 화면 녹화. 카메라 프리뷰 위에 상품명, 신뢰도, Top-3이 실시간 표시된다.
좌: 4주차 PH+Color only / 우: 5주차 PH+Color+OCR (이미지 압축 적용 후 응답 속도 개선)
5가지 피처 조합에 대해 201개 등록 이미지를 Leave-One-Out 교차검증으로 평가하였다. 각 이미지를 하나씩 빼고 나머지로 DB를 구성한 뒤, 빠진 이미지의 상품을 맞추는 과정을 201회 반복한다.
| Feature Combination | Dimension | Correct | Total | Accuracy |
|---|---|---|---|---|
| PH only | 54D | 157 | 201 | 78.11% |
| Color only | 96D | 171 | 201 | 85.07% |
| PH + Color | 150D | 188 | 201 | 93.53% |
| OCR only | text | 98 | 201 | 48.76% |
| PH + Color + OCR | 150D + text | 189 | 201 | 94.03% |
PH 단독 78%, Color 단독 85%이지만 결합 시 93.5%로 도약한다.
PH는 형태(topology), Color는 색상 분포(histogram)를 포착하여
한쪽이 틀리는 경우를 다른 쪽이 보완한다.
위상 정보가 독립적 가치를 제공한다는 TDA 연구의 핵심 증거.
OCR 단독 48.76%로 주역은 아니지만,
PH+Color가 혼동하는 상품 쌍에서 결정적 보너스를 제공한다 (93.53% → 94.03%).
OCR weight 탐색 결과 w=1.0에서 최적이며,
w≥1.0에서 포화(saturated)된다.
| 상품 | 이미지 | 정답 | 정확도 |
|---|---|---|---|
| cookie | 20 | 20 | 100% |
| orthomol | 21 | 21 | 100% |
| tubing band | 20 | 20 | 100% |
| Philips JC302 | 21 | 20 | 95.24% |
| kitkat | 20 | 19 | 95.00% |
| pokemon go++ | 20 | 19 | 95.00% |
| Airpods Pro | 20 | 18 | 90.00% |
| every time | 20 | 18 | 90.00% |
| kavalan | 19 | 17 | 89.47% |
| stanley | 20 | 17 | 85.00% |
adjusted = L2_distance − (OCR_similarity × weight)
| Weight | Correct | Accuracy |
|---|---|---|
| 0.5 | 188 | 93.53% |
| 1.0 | 189 | 94.03% |
| 1.5 | 189 | 94.03% |
| 2.0 | 189 | 94.03% |
| 3.0 | 189 | 94.03% |
| 5.0 | 189 | 94.03% |
4주차(PH+Color only)와 5주차(PH+Color+OCR)의 실제 스캔 결과를 비교한다. 동일한 10종 상품을 같은 앱으로 스캔하되, 서버 파이프라인에 OCR이 추가된 것이 유일한 차이다.
| 상품 | 4주차 (OCR 없음) | 5주차 (OCR 적용) | 변화 |
|---|---|---|---|
| pokemon go ++ | 71.4% (10/14) | 100% (9/9) | +28.6%p |
| tubing band | 0% (0/3) | 85.7% (6/7) | +85.7%p |
| Philips JC302 | 50.0% (4/8) | 75.0% (6/8) | +25.0%p |
| Airpods Pro | 57.1% (4/7) | 77.8% (7/9) | +20.7%p |
| orthomol | 100% (3/3) | 88.9% (8/9) | -11.1%p |
| every time | 100% (8/8) | 100% (7/7) | 0 |
| cookie | 100% (5/5) | 100% (8/8) | 0 |
| kavalan | 0% (0/2) | 0% (0/6) | 0% |
Android 앱에서 실시간 스캔 후 O/X 판정한 화면. PH+Color+OCR 파이프라인이 상품명, 신뢰도, Top-3을 표시한다.
텍스트가 뚜렷한 상품(tubing band, pokemon go ++)에서 극적 개선.
4주차 오인식 21건 → 5주차 14건으로 33% 감소.
OCR 유사도 보너스가 PH+Color 거리만으로 구별 어려운 상품을 분리해준다.
kavalan 0% — OCR 적용 후에도 6회 연속 실패. 등록 이미지 다양성 부족이 근본 원인.
촬영 조건 변동 — 조명/각도/거리 차이가 피처 벡터를 변형시켜 등록 벡터와의 거리가 벌어진다.
피처 설계가 아닌 데이터 다양성의 문제
상품 이미지에서 Persistent Homology(PH)로 위상적 특징 54D, Color Histogram으로 색상 분포 96D, OCR로 텍스트를 추출하여 총 150D 벡터 + 텍스트 유사도로 상품을 식별하는 시스템을 구축하였다. 11종 상품 211개 등록 이미지에 대해 Leave-One-Out 교차검증으로 각 피처의 기여도를 측정하고, 153건의 실제 스캔(4주차 78건 + 5주차 75건)으로 OCR 기여를 실전 검증하였다. 총 364장의 이미지를 처리하였다.
LOO 94.03%뿐 아니라 실전 스캔에서도 78.5%를 달성하였다. OCR 없이 66.7%에서 OCR 적용 후 78.5%로 +11.8%p 향상. tubing band 0%→86%, pokemon go++ 71%→100% 등 텍스트가 뚜렷한 상품에서 특히 효과적이다.
LOO 94%와 실전 78.5%의 잔여 gap 15.6%p는 kavalan(0/6, 0%)이 대표적 사례로, 등록 이미지의 다양성 부족에서 기인한다. 피처 설계 자체의 한계가 아니며, 다양한 조건의 등록 이미지 확보로 해결 가능하다.
딥러닝과 달리 학습 데이터 없이 등록 즉시 식별이 가능하다. CPU만으로 0.7초 내 응답하며, 신규 상품을 재학습 없이 추가할 수 있다. Android + iOS 앱으로 실제 동작하는 시스템을 구현하였다.
Persistent Homology는 상품 이미지 식별에서 유의미한 위상적 특징을 제공하며, Color Histogram, OCR과 결합 시 상보적으로 작용하여 실전 스캔 78.5%를 달성한다. OCR 적용 전후 비교를 통해 +11.8%p의 실전 기여가 검증되었으며, 잔여 gap 15.6%p(LOO 94% vs 실전 78.5%)는 등록 이미지 다양성 확보로 줄일 수 있다. PH 기반 피처는 추가 연구(Wasserstein distance, persistence image, data augmentation)를 통해 더 높은 실전 정확도 도달이 가능하다.
| 용도 | 도구 | 버전 | 라이선스 |
|---|---|---|---|
| PH 계산 | GUDHI | 3.12.0 | MIT |
| 이미지 처리 + Color | OpenCV | 4.13.0 | Apache 2.0 |
| OCR 엔진 | Tesseract | 5.5.0 | Apache 2.0 |
| Android | CameraX + Retrofit 2 | — | Apache 2.0 |
| iOS | SwiftUI + AVFoundation | — | MIT |
| Server | Spring Boot + MySQL | 3.5 / 8.4 | Apache / GPL |
이하 주차별 상세 실험 로그는 한국어로 제공됩니다.
Feature Ablation Study로 PH/Color/OCR 기여도를 정량 측정(LOO 94.03%)하고,
OCR을 스캔 파이프라인에 통합한 뒤 실제 스캔으로 OCR 기여를 검증하였다.
등록 상품 기준 66.7% → 78.5% (+11.8%p) 향상 확인.
5가지 피처 조합에 대해 201개 등록 이미지를 Leave-One-Out 교차검증으로 평가하였다.
각 이미지를 하나씩 빼고 나머지로 DB를 구성한 뒤, 빠진 이미지의 상품을 맞추는 과정을 201회 반복한다.
| Feature Combination | Dimension | Correct | Total | Accuracy |
|---|---|---|---|---|
| PH only | 54D | 157 | 201 | 78.11% |
| Color only | 96D | 171 | 201 | 85.07% |
| PH + Color | 150D | 188 | 201 | 93.53% |
| OCR only | text | 98 | 201 | 48.76% |
| PH + Color + OCR | 150D + text | 189 | 201 | 94.03% |
PH + Color 상보성 — PH 단독 78.11%, Color 단독 85.07%이지만 결합 시 93.53%로 도약한다. PH는 형태(topology), Color는 색상 분포(histogram)를 포착하여 서로 다른 차원의 정보를 제공하므로, 한쪽이 틀리는 경우를 다른 쪽이 보완한다.
OCR의 역할 — OCR 단독 48.76%로 독립적 판별력은 낮지만, PH+Color가 혼동하는 상품 쌍에서 결정적 보너스를 제공하여 93.53% → 94.03%로 개선한다. OCR weight 탐색 결과 w=1.0에서 최적이며, w≥1.0에서 포화(saturated)된다.
LOO vs 실전 갭 — LOO 94.03% vs 실제 스캔 57.69%로 36.3%p 차이가 존재한다. 촬영 조건(각도, 거리, 조명)의 변동이 주 원인이며, 등록 시 다양한 조건에서 촬영(data augmentation)하면 갭을 줄일 수 있다.
adjusted_distance = L2_distance − (OCR_similarity × weight).
weight를 0.5~5.0까지 탐색한 결과, w=1.0에서 최적 성능을 달성한다.
| OCR Weight | Correct | Total | Accuracy |
|---|---|---|---|
| 0.5 | 188 | 201 | 93.53% |
| 1.0 | 189 | 201 | 94.03% |
| 1.5 | 189 | 201 | 94.03% |
| 2.0 | 189 | 201 | 94.03% |
| 3.0 | 189 | 201 | 94.03% |
| 5.0 | 189 | 201 | 94.03% |
| 상품 | 등록 이미지 | 정답 | 정확도 |
|---|---|---|---|
| cookie | 20 | 20 | 100% |
| orthomol | 21 | 21 | 100% |
| tubing band | 20 | 20 | 100% |
| Philips JC302 | 21 | 20 | 95.24% |
| kitkat | 20 | 19 | 95.00% |
| pokemon go++ | 20 | 19 | 95.00% |
| Airpods Pro | 20 | 18 | 90.00% |
| every time | 20 | 18 | 90.00% |
| kavalan | 19 | 17 | 89.47% |
| stanley | 20 | 17 | 85.00% |
128×128 리사이즈 후 OCR을 적용하면 글자가 뭉개지는 문제가 있었다. 해결: 원본 해상도 center_crop에서 OCR을 먼저 추출하고, 이후 128×128로 리사이즈하여 PH/Color를 계산한다.
# Scan pipeline (identify_ph_color.py)
img = Image.open(path).convert("RGB")
cropped = center_crop(img) # 3:4 ratio
ocr_text = extract_ocr_text(cropped) # OCR on original resolution
gray_128 = cv2.resize(gray, (128,128))
color_128 = cv2.resize(rgb, (128,128))
ph = ph_features_54d(gray_128) # PH 54D (3 filtrations)
color = color_features_96d(color_128) # Color 96D (H32+S32+V32)
OCR 텍스트 유사도는 단어 Jaccard와 문자 트라이그램 Jaccard 중 큰 값을 취한다. 트라이그램은 OCR 노이즈(오타, 깨진 문자)에 강건하다. 0°/180° 회전 중 더 많은 문자를 인식하는 방향을 선택한다.
| 용도 | 도구 | 버전 | 라이선스 |
|---|---|---|---|
| PH 계산 | GUDHI | 3.12.0 | MIT |
| 이미지 처리 + Color Histogram | OpenCV | 4.13.0 | Apache 2.0 |
| OCR 엔진 | Tesseract | 5.5.0 | Apache 2.0 |
| Android 앱 | CameraX + Retrofit 2 | — | Apache 2.0 |
| iOS 앱 | SwiftUI + AVFoundation | — | MIT |
| 서버 | Spring Boot + MySQL | 3.5 / 8.4 | Apache / GPL |
3주차에서 자가 테스트(DB 이미지 ↔ DB 이미지) 100%를 달성하였으나, 이는 등록된 이미지로 등록된 이미지를 찾는 것이다.
4주차에서는 등록모드(PH+Color+OCR로 상품 정보 저장)와 스캔모드(카메라로 실물을 촬영하여 판정)를 분리하고,
SAM을 제거하고 center_crop으로 통일한 뒤, 실제 스마트폰으로 10종 상품을 스캔하여 정확도를 측정하였다.
이전 주차에서는 등록 시 MobileSAM(물체 인식 크롭)을 사용했으나, 스캔 시에는 SAM 없이 center_crop을 사용했다.
SAM 크롭과 center_crop이 만드는 이미지가 다르기 때문에 — 같은 상품을 찍어도
피처 벡터가 완전히 다른 공간에 놓이는 문제가 발생하였다 (PH L2 차이: 5,267).
등록과 스캔 모두 center_crop(3:4 비율 중앙 크롭)으로 통일하여 피처 공간 불일치를 해결하였다.
3주차에서는 Min-Max 정규화를 사용했다. 그러나 Min-Max는 쿼리마다 최소/최대가 바뀌어 결과가 불안정하다.
4주차에서 Z-score 정규화로 전환하여 DB 전체의 평균(μ)과 표준편차(σ)를 기준으로 정규화한다.
(x - min) / (max - min)(x - μ) / σ
자가 테스트는 DB에 등록된 이미지를 다시 쿼리로 넣는 것이다. 같은 이미지이므로 100%가 당연하다.
실제 스캔은 스마트폰 카메라로 실물 상품을 촬영한다. 조명, 각도, 거리, 배경이 모두 달라진다.
이 차이가 정확도 100% → 69.0% 하락의 원인이다.
| Product | 스캔 | 정답 | 정확도 | 주요 오판 |
|---|---|---|---|---|
| PhilipsJC302 | 5 | 5 | 100% | — |
| orthomol | 8 | 8 | 100% | — |
| cookie | 6 | 6 | 100% | — |
| every time | 4 | 3 | 75% | → kitkat ×1 |
| pokemon go | 5 | 3 | 60% | → PhilipsJC302 ×2 |
| tubing band | 5 | 3 | 60% | → kavalan ×2 |
| stanley | 3 | 0 | 0% | → every time ×3 |
| kavalan | 4 | 0 | 0% | → every time ×3, kitkat ×1 |
| kitkat | 1 | 0 | 0% | → every time ×1 |
| 정답없음 (미등록) | 3 | 0 | — | pokemongo, kitkat, everytime으로 오분류 |
오판이 특정 상품 쌍에 집중된다. stanley → every time (3회), kavalan → every time/kitkat (4회), tubingband → kavalan (2회).
every time이 강한 어트랙터로 작용하여, stanley·kavalan·kitkat이 모두 every time으로 끌린다.
PH+Color 만으로는 이 유사성을 구분하지 못한다 — 텍스트(OCR)가 구분의 열쇠가 될 수 있다.
Android 앱의 스캔모드에서 실제 상품을 카메라로 비추고, O(정답)/X(오답) 버튼으로 판정한 결과이다.
상단에 예측 상품명과 신뢰도, 하단에 Top-3 매칭 결과와 서버 응답 시간이 표시된다.










신뢰도는 1위와 2위의 거리 차이를 나타낸다: confidence = (d₂ - d₁) / d₂
값이 클수록 1위가 확실히 가깝고, 작으면 1위와 2위가 비슷하다는 뜻이다.
실제 결과에서 정답도 오답도 대부분 0.002~0.17 범위로 낮았다 —
상품 간 거리가 전반적으로 비슷하여 신뢰도만으로 정답/오답을 구분하기 어렵다.
자가 테스트 100%와 실제 스캔 69.0%의 차이는 카메라 촬영 환경의 변동성(조명, 각도, 거리)이 원인이다.
등록된 이미지는 고정된 조건에서 촬영되었지만, 실제 스캔은 매번 다른 조건에서 촬영된다.
9개 상품 중 3개(PhilipsJC302, orthomol, cookie)가 100%를 달성했지만,
stanley(0%), kavalan(0%), kitkat(0%)에서 전혀 인식에 실패하였고, every time(75%), pokemongo·tubingband(60%)도 불완전하다.
그러나 랜덤(10%) 대비 PH+Color(69.0%)는 의미 있는 개선이며,
PH 피처(위상적 형태 정보)가 색상 정보와 결합하여 식별력에 기여한다는 근거가 된다.
every time이 어트랙터로 작용하여 stanley·kavalan·kitkat을 끌어당기는 패턴이 확인되었으며,
텍스트가 뚜렷한 상품의 혼동은 OCR 추가가 해소의 열쇠가 될 수 있다.
| 용도 | 도구 | 버전 | 라이선스 |
|---|---|---|---|
| PH 계산 | GUDHI | 3.12.0 | MIT |
| 이미지 처리 + Color Histogram | OpenCV | 4.13.0 | Apache 2.0 |
| OCR 엔진 (등록모드) | Tesseract | 5.5.0 | Apache 2.0 |
| Android 앱 | CameraX + Retrofit 2 | — | Apache 2.0 |
| 서버 | Spring Boot + MySQL | 3.5 / 8.4 | Apache / GPL |
2주차에서 PH 단독 94%의 한계를 확인하고, 색상 히스토그램(HSV)과 OCR 텍스트 인식을 결합하여
동일 100장(10종×10장)에 대해 Top-1 100%, Top-5 100%를 달성하였다.
PH는 형태, Color는 색상, OCR은 글자를 보기 때문에 세 관점이 상호 보완된다.
cv2.calcHist() 한 줄로 계산. Apache 2.0.
동일 100장에 대해 특징 조합을 바꿔가며 LOO(한 장씩 빼면서 검증) 정확도를 측정했다.
PH 거리는 수만 단위, Color 거리는 소수점, OCR 유사도는 0~1 — 단위가 제각각이라
그냥 합산하면 숫자가 큰 PH만 결과를 지배한다. 모든 거리를 0~1 범위로 맞춘 뒤(Min-Max 정규화)
동등하게 합산해야 세 특징이 공정하게 기여할 수 있다.
정규화된 값 = (원래 값 − 최소값) / (최대값 − 최소값)
| PH | Color | OCR | 합계 | |
| 정규화 전 | 5,000 | 0.1 | 0.2 | 5,000.3 (PH가 99.9%) |
| 정규화 후 | 0.3 | 0.4 | 0.5 | 1.2 (셋 다 공평) |
| Method | Dim | Top-1 | Top-5 | 설명 |
|---|---|---|---|---|
| PH 54D (baseline) | 54D | 79% | 89% | 형태만 — 정규화 적용 시 |
| Color 96D only | 96D | 97% | 99% | 색상만 — 단독으로도 매우 강력 |
| OCR only | text | 74% | 88% | 글자만 — 노이즈 多, 텍스트 뚜렷한 상품에서 유효 |
| PH + Color | 150D | 100% | 100% | Best — 형태 + 색상 결합으로 완벽 보완 |
| PH + OCR | 54D+text | 90% | 94% | 형태 + 글자 |
| PH + Color + OCR | 150D+text | 100% | 100% | 3가지 모두 결합 |
PH + Color만으로 이미 100%. OCR은 현재 추가 이득이 없지만, 같은 상품의 다른 맛/색상/사이즈 변형(예: 킷캣 오리지널 vs 딸기)처럼 박스 형태와 색은 거의 같고 글자만 다른 경우에 필수적이 된다.
| Product | PH only | Color only | OCR only | PH+Color | PH 오분류 |
|---|---|---|---|---|---|
| tubing band | 100% | 100% | 90% | 100% | — |
| cookie | 90% | 100% | 100% | 100% | → every time ×1 |
| orthomol | 90% | 100% | 80% | 100% | → Airpods Pro ×1 |
| Airpods Pro | 90% | 80% | 20% | 100% | → stanley ×1 |
| pokemon go ++ | 90% | 90% | 80% | 100% | → kitkat ×1 |
| kitkat | 80% | 100% | 100% | 100% | → pokemon ×2 |
| Philips JC302 | 70% | 100% | 100% | 100% | → every time, tubing, cookie |
| stanley | 70% | 100% | 40% | 100% | → cookie, kitkat, Airpods |
| every time | 60% | 100% | 80% | 100% | → pokemon, stanley, tubing, cookie |
| kavalan | 50% | 100% | 50% | 100% | → tubing, Philips, stanley ×2 |
Tesseract 5.5.0 (Apache 2.0, Google 유지보수)을 사용하였다. 촬영 각도와 표면 재질에 따라 인식률 차이가 크다.
| Product | 인식률 | 대표 추출 텍스트 |
|---|---|---|
| kitkat | 10/10 | sugar butter tree kitkat |
| cookie | 10/10 | premium cookie set |
| Philips JC302 | 10/10 | keep your shaver like new |
| orthomol | 10/10 | orthomol ronnefeldt tea excellence |
| every time | 10/10 | korean ginseng everytime |
| stanley | 10/10 | stanley |
| tubing band | 10/10 | (noisy, low quality) |
| kavalan | 10/10 | distillery reserve (sparse) |
| Airpods Pro | 9/10 | (mostly noise — smooth white surface) |
| pokemon go ++ | 8/10 | niantic (sparse) |
PH(형태) + Color(색상) + OCR(글자), 세 가지 관점을 결합하면
각각의 약점을 상호 보완하여 10종 100장에서 Top-1 100%, Top-5 100%를 달성한다.
PH + Color만으로 이미 100%이며, OCR은 현재 추가 이득이 없지만 —
같은 상품의 다른 맛/색상/사이즈(예: 킷캣 오리지널 vs 딸기)처럼 박스 형태와 색은 같고 글자만 다른 경우에 핵심 구분자가 된다.
핵심 발견은 Color Histogram이 단독 97%로 매우 강력하다는 점이다.
이는 현재 10종 상품의 색이 모두 다르기 때문이며, 같은 색 상품이 추가되면
Color 단독의 한계가 드러나고 PH의 형태 구분 능력이 필수적이 될 것이다.
이 세 특징을 결합한 벡터(150D + 텍스트)는 상품의 “시각적 지문(Fingerprint)”으로 기능한다.
물리적 바코드 없이, 겉모습만으로 상품을 식별하는 “TDA-based Product Fingerprint” 개념이다.
GPU나 AI 모델 없이 CPU 1~2초, 스마트폰에서 오프라인으로 동작 가능하다.
| 용도 | 도구 | 버전 | 라이선스 |
|---|---|---|---|
| PH 계산 | GUDHI | 3.12.0 | MIT |
| 이미지 처리 + Color Histogram | OpenCV | 4.13.0 | Apache 2.0 |
| OCR 엔진 | Tesseract | 5.5.0 | Apache 2.0 |
| OCR Python 래퍼 | pytesseract | 0.3.13 | Apache 2.0 |
| DB 연동 | MySQL + mysql-connector | 8.4 | GPL / MIT |
10종 100장으로 PH 분류를 검증하고, 전처리와 분류 방법을 개선하였다.
중앙 50% 고정 크롭 + 128×128 해상도 표준화 + 다중 filtration 결합으로
100번 중 94번 첫 번째 답이 정답(Top-1 94%), 5개 후보 안에 정답이 반드시 포함(Top-5 100%)을 달성하였다.
카메라 가이드 프레임 안에 상품을 놓고 촬영하면, 상품이 사진 중앙에 위치한다.
중앙 50%를 고정 크롭하여 항상 동일한 영역을 잘라내고,
128×128 grayscale로 통일하여 PH 비교의 일관성을 확보한다.
위: 원본(3024×4032) → 중앙: 50% 크롭(1512×2016) → 아래: 128×128 grayscale
10종 박스형 상품을 각 10장씩, CameraX 가이드 프레임 안에서 촬영했다.
| Product | Type | Images |
|---|---|---|
| kitkat | 초콜릿 (박스) | 10 |
| cookie | 쿠키 (박스) | 10 |
| every time | 영양제 (박스) | 10 |
| orthomol | 영양제 (박스) | 10 |
| Airpods Pro | 이어폰 (박스) | 10 |
| Philips JC302 | 면도기 세정액 (박스) | 10 |
| pokemon go ++ | 카드 (박스) | 10 |
| stanley | 텀블러 (박스) | 10 |
| kavalan | 위스키 (박스) | 10 |
| tubing band | 운동밴드 (박스) | 10 |
Top-1 = 첫 번째 답이 정답인 비율 / Top-5 = 가까운 순서로 5개를 후보로 줬을 때 그 안에 정답이 있는 비율
위 과정에서 “사진을 숫자로 변환하는 방법”과 “비교하는 방법”을 바꿔가며 정확도를 측정했다.
Sublevel(밝기값 기반) /
Edge(윤곽선 기반) /
Gradient(밝기 변화량 기반)
1-NN(가장 가까운 1장으로 판정) /
3-NN(가장 가까운 3장의 다수결) /
Centroid(상품별 평균 벡터와 비교)
| 관점 | 차원 | Top-1 | Top-5 | 설명 |
|---|---|---|---|---|
| Sublevel (밝기값) | 18D | 89% | 99% | 밝기 패턴에서 PH 추출 |
| Edge / Sobel (윤곽선) | 18D | 75% | 96% | 윤곽선에서 PH 추출 |
| Gradient / Laplacian (변화량) | 18D | 67% | 97% | 밝기 변화량에서 PH 추출 |
| Combined 54D (3관점 결합) | 54D | 94% | 100% | Best — 위 3개를 합쳐서 상호 보완 |
각 관점은 단독으로 67~89%이지만, 3개를 합치면 서로 다른 특징을 보완하여 94% / 100%를 달성한다.
같은 관점에서도 비교 방식을 바꿔 실험했다: 1-NN(가장 가까운 1장), 3-NN(3장 다수결), Centroid(평균 벡터 비교).
추가로 Persistence Image(450D), CFV 3D(핵심 값 3개) 등 다른 벡터화 방법도 시도했다.
| Method | Dim | Top-1 | Top-5 | 설명 |
|---|---|---|---|---|
| SUBLEVEL (밝기값 기반) — 비교 방식별 | ||||
| Sublevel 1-NN | 18D | 89% | 99% | 가장 가까운 1장으로 판정 |
| Sublevel 3-NN | 18D | 92% | 99% | 3장 다수결 — 안정성 향상 |
| Sublevel 5-NN | 18D | 84% | 99% | 5장 다수결 — k가 크면 오히려 하락 |
| Sublevel Centroid | 18D | 84% | 99% | 상품 평균 벡터와 비교 |
| 다른 벡터화 방법 | ||||
| CFV 3D | 3D | 52% | 92% | 핵심 값 3개만 — 해석 쉬움, 정확도 낮음 |
| Persistence Image 1-NN | 450D | 87% | 98% | birth-death 밀도 격자 — 고차원 |
| COMBINED 54D — 비교 방식별 | ||||
| Combined 54D 1-NN | 54D | 94% | 100% | Best |
| Combined 54D 3-NN | 54D | 92% | 100% | Top-5 100% 유지 |
| Combined 54D Centroid | 54D | 88% | 100% | 평균 벡터 비교 |
| 54D + PI (504D) | 504D | 91% | 99% | 차원 증가 대비 효과 제한적 |
| Product | 정답 | Accuracy | 오분류 |
|---|---|---|---|
| kitkat | 10/10 | 100% | — |
| orthomol | 10/10 | 100% | — |
| stanley | 10/10 | 100% | — |
| cookie | 9/10 | 90% | → Airpods Pro ×1 |
| every time | 9/10 | 90% | → cookie ×1 |
| Philips JC302 | 9/10 | 90% | → pokemon ×1 |
| pokemon go ++ | 9/10 | 90% | → Philips ×1 |
| tubing band | 9/10 | 90% | → pokemon ×1 |
| kavalan | 8/10 | 80% | → kitkat ×1, Airpods ×1 |
| Airpods Pro | 6/10 | 60% | → stanley ×1, cookie ×2, every time ×1 |
Cubical Complex Filtration (격자 복합체 여과) — 이미지의 밝기값을 threshold(문턱값)로 사용한다.
threshold t를 0에서 1까지 올리면, 어두운 픽셀부터 순서대로 "켜지면서" connected component(연결 성분)가 생겼다 합쳐지고, hole(구멍)이 생겼다 사라진다.
이 생성(birth)과 소멸(death)의 패턴이 곧 그 이미지의 위상적 지문이다.
Persistence Diagram (지속성 다이어그램) — 각 위상적 특징의 birth(생성)과 death(소멸)를 점으로 찍는다.
대각선에서 먼 점 = 오래 살아남은 구조 = 의미 있는 특징. 같은 상품은 다이어그램 패턴이 유사하고, 다른 상품은 다르다.
Persistence Barcode (지속성 바코드) — 각 특징의 수명을 bar(막대)로 표현한다.
긴 막대 = 노이즈가 아닌 실제 구조. 상품마다 막대의 길이 분포와 개수가 다르므로, 이를 통계적으로 요약하면 18차원 특징 벡터가 된다.
54D 벡터를 t-SNE(고차원→2D 압축 도구)로 2D로 줄이면 상품별로 깔끔하게 분리되는 것을 확인할 수 있다.
t-SNE(고차원→2D 압축 시각화)는 시각화 도구이며, 실제 정확도(94%)는 원본 54D에서 LOO(한 장씩 빼면서 검증)로 측정한 값이다.
PH는 색상도 안 보고, 글자도 안 읽고, AI 학습도 없이 —
순수하게 grayscale 밝기 패턴의 위상적 구조만으로 상품을 구분하는 방법이다.
이것만으로 10종 상품을 94% 정확도로 맞히고, 5개 후보를 주면 100% 정답이 포함된다는 것은
PH가 상품 식별에 유효한 특징을 잡아낸다는 것을 증명한다.
핵심 발견은 크롭의 일관성이다.
단순한 고정 크롭이 높은 정확도를 냈다. 항상 같은 영역을 자르면
같은 상품은 비슷하게, 다른 상품은 다르게 나오는 것이 보장되기 때문이다.
비싼 모델 없이도, CPU 1초 연산만으로 이 정도 정확도를 낼 수 있다.
다만, 현재는 10종 박스형 상품이라는 제한된 조건이다.
Airpods Pro(60%)처럼 매끈한 표면은 grayscale에서 형태 차이가 적어 구분이 어렵고,
상품 수가 늘어나면 정확도가 떨어질 수 있다. PH 단독의 한계를 넘기 위해
다음 주차에서 색상과 텍스트 정보를 결합한다.
| Component | Stack | Role |
|---|---|---|
| tda-api | Spring Boot 3.5 · Java 17 · GUDHI | REST API + 고정 크롭 + PH 계산 |
| tda-android | Java · CameraX · Android SDK 34 · Retrofit 2 | 가이드 프레임 촬영 + 결과 조회 |
| EC2 | Ubuntu 26.04 · nginx · MySQL 8.4 · Python 3.14 | 서버 인프라 |
| Image | H₀ count | H₁ count | H₀ max pers. | H₁ max pers. |
|---|---|---|---|---|
| img_01 | 5,803 | 5,534 | 247 | 27 |
| img_02 | 4,784 | 4,499 | 245 | 31 |
| img_03 | 4,869 | 4,598 | 246 | 23 |
| img_04 | 5,256 | 4,970 | 247 | 21 |
| img_05 | 4,614 | 4,326 | 240 | 24 |
| img_06 | 3,884 | 3,706 | 248 | 24 |
| img_07 | 4,698 | 4,419 | 246 | 27 |
| img_08 | 4,826 | 4,560 | 249 | 32 |
| img_09 | 4,979 | 4,697 | 245 | 28 |
| img_10 | 4,654 | 4,377 | 246 | 27 |
동일 상품(kitkat) 10장을 각도·거리·조명을 달리하며 촬영하고
PH 특징 벡터를 비교한 결과,
H₀ max persistence 240~249, H₀ count 3,884~5,803으로
모든 이미지가 일정 범위 안에 모이는 것을 확인했다.
즉, 촬영 조건이 달라져도 같은 상품의 위상적 구조는 안정적으로 유지된다.
이는 PH가 같은 상품을 "같다"고 인식할 수 있음을 의미한다.
다음 주에는 여러 종류의 상품을 촬영하여,
서로 다른 상품끼리도 PH로 구별이 가능한지 검증하겠다.