# -*- coding: utf-8 -*- """ ONNX vs PaddlePaddle 상세 텍스트 결과 비교 """ import os import sys import time import logging from typing import Dict, List # 모듈 경로 추가 sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src')) # 가짜 GPU 매니저 및 로거 클래스 class MockGPUManager: def __init__(self, can_use_cuda=True): self.can_use_cuda = can_use_cuda class MockLogger: def log(self, message: str, level=logging.INFO, exc_info=False): pass # 조용한 로거 def compare_ocr_results(): """ONNX와 PaddlePaddle OCR 결과 상세 비교""" print("🔍 ONNX vs PaddlePaddle 텍스트 감지 결과 상세 비교") print("=" * 70) test_image = os.path.join(os.path.dirname(__file__), "1.jpg") if not os.path.exists(test_image): print(f"❌ 테스트 이미지를 찾을 수 없습니다: {test_image}") return logger = MockLogger() gpu_manager = MockGPUManager(can_use_cuda=True) # 1. ONNX CPU 결과 수집 print("\n🔧 ONNX CPU 결과 수집 중...") try: from onnx_ocr_module import ONNXOCRModule ocr_onnx_cpu = ONNXOCRModule( logger=logger, gpu_manager=gpu_manager, execution_provider='cpu' ) start_time = time.time() onnx_cpu_results = ocr_onnx_cpu.detect_text(test_image) onnx_cpu_time = (time.time() - start_time) * 1000 print(f"✅ ONNX CPU: {len(onnx_cpu_results)}개 텍스트, {onnx_cpu_time:.1f}ms") except Exception as e: print(f"❌ ONNX CPU 실패: {e}") onnx_cpu_results = [] onnx_cpu_time = 0 # 2. ONNX CUDA 결과 수집 print("\n🚀 ONNX CUDA 결과 수집 중...") try: ocr_onnx_cuda = ONNXOCRModule( logger=logger, gpu_manager=gpu_manager, execution_provider='cuda' ) start_time = time.time() onnx_cuda_results = ocr_onnx_cuda.detect_text(test_image) onnx_cuda_time = (time.time() - start_time) * 1000 print(f"✅ ONNX CUDA: {len(onnx_cuda_results)}개 텍스트, {onnx_cuda_time:.1f}ms") except Exception as e: print(f"❌ ONNX CUDA 실패: {e}") onnx_cuda_results = [] onnx_cuda_time = 0 # 3. PaddlePaddle CPU 결과 수집 print("\n🐼 PaddlePaddle CPU 결과 수집 중...") try: from paddleocr import PaddleOCR ocr_paddle_cpu = PaddleOCR(use_gpu=False, use_angle_cls=True, lang='ch', show_log=False) start_time = time.time() paddle_cpu_raw = ocr_paddle_cpu.ocr(test_image) paddle_cpu_time = (time.time() - start_time) * 1000 # PaddleOCR 결과 파싱 paddle_cpu_results = [] if paddle_cpu_raw and paddle_cpu_raw[0]: for i, line in enumerate(paddle_cpu_raw[0]): if len(line) >= 2: polygon = line[0] text = line[1][0] confidence = line[1][1] # 바운딩 박스 계산 import numpy as np import cv2 polygon_np = np.array(polygon, dtype=np.int32) x, y, w, h = cv2.boundingRect(polygon_np) paddle_cpu_results.append({ 'text': text, 'confidence': confidence, 'polygon': polygon, 'bbox': (x, y, w, h), 'method': 'paddle' }) print(f"✅ Paddle CPU: {len(paddle_cpu_results)}개 텍스트, {paddle_cpu_time:.1f}ms") except Exception as e: print(f"❌ PaddlePaddle CPU 실패: {e}") paddle_cpu_results = [] paddle_cpu_time = 0 # 4. PaddlePaddle CUDA 결과 수집 print("\n🐼🚀 PaddlePaddle CUDA 결과 수집 중...") try: ocr_paddle_cuda = PaddleOCR(use_gpu=True, use_angle_cls=True, lang='ch', show_log=False) start_time = time.time() paddle_cuda_raw = ocr_paddle_cuda.ocr(test_image) paddle_cuda_time = (time.time() - start_time) * 1000 # PaddleOCR 결과 파싱 paddle_cuda_results = [] if paddle_cuda_raw and paddle_cuda_raw[0]: for i, line in enumerate(paddle_cuda_raw[0]): if len(line) >= 2: polygon = line[0] text = line[1][0] confidence = line[1][1] # 바운딩 박스 계산 import numpy as np import cv2 polygon_np = np.array(polygon, dtype=np.int32) x, y, w, h = cv2.boundingRect(polygon_np) paddle_cuda_results.append({ 'text': text, 'confidence': confidence, 'polygon': polygon, 'bbox': (x, y, w, h), 'method': 'paddle' }) print(f"✅ Paddle CUDA: {len(paddle_cuda_results)}개 텍스트, {paddle_cuda_time:.1f}ms") except Exception as e: print(f"❌ PaddlePaddle CUDA 실패: {e}") paddle_cuda_results = [] paddle_cuda_time = 0 # 5. 결과 상세 비교 print("\n" + "="*70) print("📊 텍스트 감지 결과 상세 비교") print("="*70) # 성능 비교 print(f"\n⚡ 성능 비교:") print(f"{'모델':<20} {'시간(ms)':<12} {'텍스트 수':<10}") print("-" * 42) print(f"{'ONNX CPU':<20} {onnx_cpu_time:<12.1f} {len(onnx_cpu_results):<10}") print(f"{'ONNX CUDA':<20} {onnx_cuda_time:<12.1f} {len(onnx_cuda_results):<10}") print(f"{'Paddle CPU':<20} {paddle_cpu_time:<12.1f} {len(paddle_cpu_results):<10}") print(f"{'Paddle CUDA':<20} {paddle_cuda_time:<12.1f} {len(paddle_cuda_results):<10}") # 텍스트 내용 비교 (ONNX CUDA vs Paddle CUDA) print(f"\n📝 텍스트 내용 상세 비교 (ONNX CUDA vs Paddle CUDA):") print("-" * 70) if onnx_cuda_results and paddle_cuda_results: print(f"\n🔧 ONNX CUDA 감지 텍스트 ({len(onnx_cuda_results)}개):") for i, result in enumerate(onnx_cuda_results, 1): text = result['text'] conf = result['confidence'] bbox = result['bbox'] print(f" {i:2d}. '{text}' (신뢰도: {conf:.3f}, 위치: {bbox})") print(f"\n🐼 Paddle CUDA 감지 텍스트 ({len(paddle_cuda_results)}개):") for i, result in enumerate(paddle_cuda_results, 1): text = result['text'] conf = result['confidence'] bbox = result['bbox'] print(f" {i:2d}. '{text}' (신뢰도: {conf:.3f}, 위치: {bbox})") # 텍스트 세트 비교 onnx_texts = set(r['text'] for r in onnx_cuda_results if r['text'].strip()) paddle_texts = set(r['text'] for r in paddle_cuda_results if r['text'].strip()) # ONNX에만 있는 텍스트 onnx_only = onnx_texts - paddle_texts if onnx_only: print(f"\n🆕 ONNX에서만 발견된 텍스트 ({len(onnx_only)}개):") for text in sorted(onnx_only): # 해당 텍스트의 신뢰도와 위치 찾기 for result in onnx_cuda_results: if result['text'] == text: print(f" - '{text}' (신뢰도: {result['confidence']:.3f}, 위치: {result['bbox']})") break # Paddle에만 있는 텍스트 paddle_only = paddle_texts - onnx_texts if paddle_only: print(f"\n🆕 Paddle에서만 발견된 텍스트 ({len(paddle_only)}개):") for text in sorted(paddle_only): # 해당 텍스트의 신뢰도와 위치 찾기 for result in paddle_cuda_results: if result['text'] == text: print(f" - '{text}' (신뢰도: {result['confidence']:.3f}, 위치: {result['bbox']})") break # 공통 텍스트 common_texts = onnx_texts & paddle_texts if common_texts: print(f"\n🤝 공통으로 발견된 텍스트 ({len(common_texts)}개):") for text in sorted(common_texts): # 신뢰도 비교 onnx_conf = next((r['confidence'] for r in onnx_cuda_results if r['text'] == text), 0) paddle_conf = next((r['confidence'] for r in paddle_cuda_results if r['text'] == text), 0) conf_diff = onnx_conf - paddle_conf conf_symbol = "🟢" if conf_diff > 0.1 else "🔴" if conf_diff < -0.1 else "🟡" print(f" {conf_symbol} '{text}' | ONNX: {onnx_conf:.3f} vs Paddle: {paddle_conf:.3f} (차이: {conf_diff:+.3f})") print("\n🎯 분석 결론:") if len(onnx_cuda_results) > len(paddle_cuda_results): diff = len(onnx_cuda_results) - len(paddle_cuda_results) print(f"✅ ONNX가 {diff}개 더 많은 텍스트를 감지했습니다!") elif len(paddle_cuda_results) > len(onnx_cuda_results): diff = len(paddle_cuda_results) - len(onnx_cuda_results) print(f"⚠️ Paddle이 {diff}개 더 많은 텍스트를 감지했습니다.") else: print("🟰 두 모델이 동일한 수의 텍스트를 감지했습니다.") if __name__ == "__main__": compare_ocr_results()