593 lines
24 KiB
Python
593 lines
24 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
출력 모듈 - 번역 결과를 시각적으로 비교하고 출력
|
||
원본, 인페인팅, 최종 결과를 나란히 배치하여 한눈에 볼 수 있게 합니다.
|
||
"""
|
||
|
||
import cv2
|
||
import numpy as np
|
||
from typing import List, Dict, Any, Tuple, Optional
|
||
import os
|
||
from datetime import datetime
|
||
import json
|
||
|
||
class OutputModule:
|
||
def __init__(self):
|
||
"""출력 모듈 초기화"""
|
||
self.output_history = []
|
||
print("출력 모듈 초기화 완료")
|
||
|
||
def create_comparison_output(self, original_path: str, inpainted_image: np.ndarray,
|
||
final_image: np.ndarray, output_dir: str,
|
||
inpainting_method: str = "unknown") -> str:
|
||
"""
|
||
원본, 인페인팅, 최종 결과를 비교하는 출력 이미지 생성
|
||
|
||
Args:
|
||
original_path (str): 원본 이미지 경로
|
||
inpainted_image (np.ndarray): 인페인팅된 이미지
|
||
final_image (np.ndarray): 최종 번역 결과 이미지
|
||
output_dir (str): 출력 디렉토리
|
||
inpainting_method (str): 사용된 인페인팅 방법
|
||
|
||
Returns:
|
||
str: 생성된 비교 이미지 경로
|
||
"""
|
||
# 원본 이미지 로드
|
||
original_image = cv2.imread(original_path)
|
||
if original_image is None:
|
||
print(f"원본 이미지를 읽을 수 없습니다: {original_path}")
|
||
return None
|
||
|
||
# 출력 디렉토리 생성
|
||
os.makedirs(output_dir, exist_ok=True)
|
||
|
||
# 비교 이미지 생성
|
||
comparison_image = self._create_three_panel_comparison(
|
||
original_image, inpainted_image, final_image, inpainting_method
|
||
)
|
||
|
||
# 파일명 생성 (타임스탬프 포함)
|
||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||
original_name = os.path.splitext(os.path.basename(original_path))[0]
|
||
|
||
# 개별 이미지 저장
|
||
original_img_path = os.path.join(output_dir, f"{original_name}_{inpainting_method}_{timestamp}_original.jpg")
|
||
inpainted_img_path = os.path.join(output_dir, f"{original_name}_{inpainting_method}_{timestamp}_inpainted.jpg")
|
||
final_img_path = os.path.join(output_dir, f"{original_name}_{inpainting_method}_{timestamp}_final.jpg")
|
||
cv2.imwrite(original_img_path, original_image)
|
||
cv2.imwrite(inpainted_img_path, inpainted_image)
|
||
cv2.imwrite(final_img_path, final_image)
|
||
|
||
# 비교 이미지 저장 (기존처럼)
|
||
output_filename = f"{original_name}_{inpainting_method}_{timestamp}_comparison.jpg"
|
||
output_path = os.path.join(output_dir, output_filename)
|
||
cv2.imwrite(output_path, comparison_image)
|
||
|
||
# 메타데이터 저장
|
||
self._save_metadata(output_dir, output_filename, {
|
||
'original_path': original_path,
|
||
'inpainting_method': inpainting_method,
|
||
'timestamp': timestamp,
|
||
'output_path': output_path,
|
||
'original_img_path': original_img_path,
|
||
'inpainted_img_path': inpainted_img_path,
|
||
'final_img_path': final_img_path
|
||
})
|
||
|
||
# 히스토리에 추가
|
||
self.output_history.append({
|
||
'timestamp': timestamp,
|
||
'original_path': original_path,
|
||
'output_path': output_path,
|
||
'inpainting_method': inpainting_method,
|
||
'original_img_path': original_img_path,
|
||
'inpainted_img_path': inpainted_img_path,
|
||
'final_img_path': final_img_path
|
||
})
|
||
|
||
print(f"개별 이미지 저장 완료: {original_img_path}, {inpainted_img_path}, {final_img_path}")
|
||
print(f"비교 이미지 생성 완료: {output_path}")
|
||
return output_path
|
||
|
||
def _create_three_panel_comparison(self, original: np.ndarray, inpainted: np.ndarray,
|
||
final: np.ndarray, method: str) -> np.ndarray:
|
||
"""
|
||
3개 패널 비교 이미지 생성
|
||
|
||
Args:
|
||
original (np.ndarray): 원본 이미지
|
||
inpainted (np.ndarray): 인페인팅된 이미지
|
||
final (np.ndarray): 최종 결과 이미지
|
||
method (str): 인페인팅 방법
|
||
|
||
Returns:
|
||
np.ndarray: 비교 이미지
|
||
"""
|
||
# 이미지 크기 통일
|
||
target_height = 400
|
||
|
||
# 원본 이미지 크기에 맞춰 너비 계산
|
||
original_height, original_width = original.shape[:2]
|
||
target_width = int(target_height * original_width / original_height)
|
||
|
||
# 각 이미지 리사이즈
|
||
original_resized = cv2.resize(original, (target_width, target_height))
|
||
inpainted_resized = cv2.resize(inpainted, (target_width, target_height))
|
||
final_resized = cv2.resize(final, (target_width, target_height))
|
||
|
||
# 비교 이미지 캔버스 생성
|
||
panel_spacing = 10
|
||
header_height = 60
|
||
footer_height = 40
|
||
|
||
total_width = target_width * 3 + panel_spacing * 2
|
||
total_height = target_height + header_height + footer_height
|
||
|
||
comparison = np.ones((total_height, total_width, 3), dtype=np.uint8) * 255
|
||
|
||
# 헤더 영역 (제목)
|
||
cv2.rectangle(comparison, (0, 0), (total_width, header_height), (240, 240, 240), -1)
|
||
|
||
# 제목 텍스트
|
||
title = f"Image Translation Result - Method: {method.upper()}"
|
||
title_size = cv2.getTextSize(title, cv2.FONT_HERSHEY_SIMPLEX, 0.8, 2)[0]
|
||
title_x = (total_width - title_size[0]) // 2
|
||
cv2.putText(comparison, title, (title_x, 35),
|
||
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (50, 50, 50), 2)
|
||
|
||
# 이미지 배치
|
||
y_offset = header_height
|
||
|
||
# 원본 이미지
|
||
x1 = 0
|
||
comparison[y_offset:y_offset+target_height, x1:x1+target_width] = original_resized
|
||
|
||
# 인페인팅된 이미지
|
||
x2 = target_width + panel_spacing
|
||
comparison[y_offset:y_offset+target_height, x2:x2+target_width] = inpainted_resized
|
||
|
||
# 최종 결과 이미지
|
||
x3 = target_width * 2 + panel_spacing * 2
|
||
comparison[y_offset:y_offset+target_height, x3:x3+target_width] = final_resized
|
||
|
||
# 라벨 추가
|
||
labels = ["Original", "Inpainted", "Final Result"]
|
||
label_positions = [x1, x2, x3]
|
||
|
||
for label, x_pos in zip(labels, label_positions):
|
||
# 라벨 배경
|
||
label_bg_y = y_offset + target_height + 5
|
||
cv2.rectangle(comparison,
|
||
(x_pos, label_bg_y),
|
||
(x_pos + target_width, label_bg_y + 30),
|
||
(220, 220, 220), -1)
|
||
|
||
# 라벨 텍스트
|
||
label_size = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.6, 2)[0]
|
||
label_x = x_pos + (target_width - label_size[0]) // 2
|
||
cv2.putText(comparison, label, (label_x, label_bg_y + 20),
|
||
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (50, 50, 50), 2)
|
||
|
||
# 구분선 추가
|
||
line_color = (200, 200, 200)
|
||
cv2.line(comparison, (target_width + panel_spacing//2, header_height),
|
||
(target_width + panel_spacing//2, y_offset + target_height), line_color, 2)
|
||
cv2.line(comparison, (target_width*2 + panel_spacing + panel_spacing//2, header_height),
|
||
(target_width*2 + panel_spacing + panel_spacing//2, y_offset + target_height), line_color, 2)
|
||
|
||
return comparison
|
||
|
||
def create_detailed_output(self, original_path: str, ocr_results: List[Dict],
|
||
translated_texts: List[str], inpainted_image: np.ndarray,
|
||
final_image: np.ndarray, output_dir: str,
|
||
inpainting_method: str) -> str:
|
||
"""
|
||
상세 정보가 포함된 출력 생성
|
||
|
||
Args:
|
||
original_path (str): 원본 이미지 경로
|
||
ocr_results (List[Dict]): OCR 결과
|
||
translated_texts (List[str]): 번역 결과
|
||
inpainted_image (np.ndarray): 인페인팅된 이미지
|
||
final_image (np.ndarray): 최종 결과
|
||
output_dir (str): 출력 디렉토리
|
||
inpainting_method (str): 인페인팅 방법
|
||
|
||
Returns:
|
||
str: 생성된 상세 출력 경로
|
||
"""
|
||
# 기본 비교 이미지 생성
|
||
comparison_path = self.create_comparison_output(
|
||
original_path, inpainted_image, final_image, output_dir, inpainting_method
|
||
)
|
||
|
||
# 상세 정보 이미지 생성
|
||
detail_image = self._create_detail_panel(ocr_results, translated_texts, inpainting_method)
|
||
|
||
# 전체 이미지 결합
|
||
comparison_image = cv2.imread(comparison_path)
|
||
combined_image = self._combine_comparison_and_detail(comparison_image, detail_image)
|
||
|
||
# 상세 출력 저장
|
||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||
original_name = os.path.splitext(os.path.basename(original_path))[0]
|
||
detail_filename = f"{original_name}_{inpainting_method}_{timestamp}_detailed.jpg"
|
||
detail_path = os.path.join(output_dir, detail_filename)
|
||
|
||
cv2.imwrite(detail_path, combined_image)
|
||
|
||
print(f"상세 출력 생성 완료: {detail_path}")
|
||
return detail_path
|
||
|
||
def _create_detail_panel(self, ocr_results: List[Dict], translated_texts: List[str],
|
||
method: str) -> np.ndarray:
|
||
"""
|
||
상세 정보 패널 생성
|
||
|
||
Args:
|
||
ocr_results (List[Dict]): OCR 결과
|
||
translated_texts (List[str]): 번역 결과
|
||
method (str): 인페인팅 방법
|
||
|
||
Returns:
|
||
np.ndarray: 상세 정보 패널 이미지
|
||
"""
|
||
# 패널 크기 계산
|
||
panel_width = 400
|
||
line_height = 25
|
||
header_height = 40
|
||
padding = 20
|
||
|
||
num_texts = len(ocr_results)
|
||
panel_height = header_height + (num_texts * line_height * 3) + padding * 2
|
||
|
||
# 패널 생성
|
||
panel = np.ones((panel_height, panel_width, 3), dtype=np.uint8) * 250
|
||
|
||
# 헤더
|
||
cv2.rectangle(panel, (0, 0), (panel_width, header_height), (200, 200, 200), -1)
|
||
cv2.putText(panel, "Translation Details", (10, 25),
|
||
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (50, 50, 50), 2)
|
||
|
||
# 방법 정보
|
||
method_text = f"Method: {method}"
|
||
cv2.putText(panel, method_text, (10, header_height + 20),
|
||
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (100, 100, 100), 1)
|
||
|
||
# 번역 정보
|
||
y_offset = header_height + 45
|
||
|
||
for i, (ocr_result, translated_text) in enumerate(zip(ocr_results, translated_texts)):
|
||
# 원본 텍스트
|
||
original_text = ocr_result['text']
|
||
confidence = ocr_result['confidence']
|
||
|
||
# 텍스트가 너무 길면 줄임
|
||
if len(original_text) > 30:
|
||
original_text = original_text[:30] + "..."
|
||
if len(translated_text) > 30:
|
||
translated_text = translated_text[:30] + "..."
|
||
|
||
# 번호
|
||
cv2.putText(panel, f"{i+1}.", (10, y_offset),
|
||
cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 0), 1)
|
||
|
||
# 원본 텍스트
|
||
cv2.putText(panel, f"CN: {original_text}", (30, y_offset),
|
||
cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 150), 1)
|
||
|
||
# 번역된 텍스트
|
||
cv2.putText(panel, f"KR: {translated_text}", (30, y_offset + 15),
|
||
cv2.FONT_HERSHEY_SIMPLEX, 0.4, (150, 0, 0), 1)
|
||
|
||
# 신뢰도
|
||
cv2.putText(panel, f"Conf: {confidence:.2f}", (30, y_offset + 30),
|
||
cv2.FONT_HERSHEY_SIMPLEX, 0.3, (100, 100, 100), 1)
|
||
|
||
y_offset += line_height * 3 + 10
|
||
|
||
# 구분선
|
||
if i < len(ocr_results) - 1:
|
||
cv2.line(panel, (20, y_offset - 5), (panel_width - 20, y_offset - 5),
|
||
(220, 220, 220), 1)
|
||
|
||
return panel
|
||
|
||
def _combine_comparison_and_detail(self, comparison: np.ndarray,
|
||
detail: np.ndarray) -> np.ndarray:
|
||
"""비교 이미지와 상세 정보 패널 결합"""
|
||
comp_height, comp_width = comparison.shape[:2]
|
||
detail_height, detail_width = detail.shape[:2]
|
||
|
||
# 높이 맞추기
|
||
if comp_height > detail_height:
|
||
# 상세 패널 높이 늘리기
|
||
extended_detail = np.ones((comp_height, detail_width, 3), dtype=np.uint8) * 250
|
||
extended_detail[:detail_height, :] = detail
|
||
detail = extended_detail
|
||
elif detail_height > comp_height:
|
||
# 비교 이미지 높이 늘리기
|
||
extended_comparison = np.ones((detail_height, comp_width, 3), dtype=np.uint8) * 255
|
||
extended_comparison[:comp_height, :] = comparison
|
||
comparison = extended_comparison
|
||
|
||
# 수평으로 결합
|
||
combined = np.hstack([comparison, detail])
|
||
|
||
return combined
|
||
|
||
def _save_metadata(self, output_dir: str, filename: str, metadata: Dict[str, Any]):
|
||
"""메타데이터를 JSON 파일로 저장"""
|
||
metadata_filename = os.path.splitext(filename)[0] + "_metadata.json"
|
||
metadata_path = os.path.join(output_dir, metadata_filename)
|
||
|
||
with open(metadata_path, 'w', encoding='utf-8') as f:
|
||
json.dump(metadata, f, ensure_ascii=False, indent=2)
|
||
|
||
def create_batch_summary(self, output_dir: str, batch_results: List[Dict]) -> str:
|
||
"""
|
||
일괄 처리 결과 요약 생성
|
||
|
||
Args:
|
||
output_dir (str): 출력 디렉토리
|
||
batch_results (List[Dict]): 일괄 처리 결과
|
||
|
||
Returns:
|
||
str: 요약 보고서 경로
|
||
"""
|
||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||
summary_filename = f"batch_summary_{timestamp}.html"
|
||
summary_path = os.path.join(output_dir, summary_filename)
|
||
|
||
# HTML 보고서 생성
|
||
html_content = self._generate_html_summary(batch_results)
|
||
|
||
with open(summary_path, 'w', encoding='utf-8') as f:
|
||
f.write(html_content)
|
||
|
||
print(f"일괄 처리 요약 생성 완료: {summary_path}")
|
||
return summary_path
|
||
|
||
def _generate_html_summary(self, batch_results: List[Dict]) -> str:
|
||
"""
|
||
일괄 처리 결과의 HTML 요약 생성
|
||
|
||
Args:
|
||
batch_results (List[Dict]): 일괄 처리 결과 리스트
|
||
|
||
Returns:
|
||
str: HTML 내용
|
||
"""
|
||
html = """
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>Batch Translation Summary</title>
|
||
<style>
|
||
body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }
|
||
.header { background: #333; color: white; padding: 20px; text-align: center; }
|
||
.summary { background: white; padding: 20px; margin: 20px 0; border-radius: 5px; }
|
||
.result-item { background: white; margin: 10px 0; padding: 15px; border-radius: 5px; border-left: 4px solid #ccc; }
|
||
.result-item.success { border-left-color: #4CAF50; }
|
||
.result-item.error { border-left-color: #f44336; }
|
||
.method-tag { background: #2196F3; color: white; padding: 2px 8px; border-radius: 3px; font-size: 12px; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="header">
|
||
<h1>Batch Translation Summary</h1>
|
||
<p>Generated: {timestamp}</p>
|
||
</div>
|
||
<div class="summary">
|
||
<h2>Overall Statistics</h2>
|
||
<p>Total Images: {total_count}</p>
|
||
<p>Successful: {success_count}</p>
|
||
<p>Failed: {failed_count}</p>
|
||
</div>
|
||
""".format(
|
||
timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||
total_count=len(batch_results),
|
||
success_count=sum(1 for r in batch_results if r.get('success', False)),
|
||
failed_count=sum(1 for r in batch_results if not r.get('success', False))
|
||
)
|
||
|
||
# 각 결과 항목 추가
|
||
for i, result in enumerate(batch_results):
|
||
status_class = "success" if result.get('success', False) else "error"
|
||
method = result.get('method', 'unknown')
|
||
|
||
html += f"""
|
||
<div class="result-item {status_class}">
|
||
<h3>Image {i+1}: {os.path.basename(result.get('original_path', 'Unknown'))}</h3>
|
||
<span class="method-tag">{method}</span>
|
||
<p><strong>Status:</strong> {'Success' if result.get('success', False) else 'Failed'}</p>
|
||
<p><strong>Processing Time:</strong> {result.get('processing_time', 'N/A')}</p>
|
||
<p><strong>Detected Texts:</strong> {result.get('text_count', 0)}</p>
|
||
</div>
|
||
"""
|
||
|
||
html += """
|
||
</body>
|
||
</html>
|
||
"""
|
||
|
||
return html
|
||
|
||
def create_slideshow(self, output_dir: str, image_paths: List[str]) -> str:
|
||
"""
|
||
결과 이미지들의 슬라이드쇼 HTML 생성
|
||
|
||
Args:
|
||
output_dir (str): 출력 디렉토리
|
||
image_paths (List[str]): 이미지 경로 리스트
|
||
|
||
Returns:
|
||
str: 슬라이드쇼 HTML 파일 경로
|
||
"""
|
||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||
slideshow_filename = f"slideshow_{timestamp}.html"
|
||
slideshow_path = os.path.join(output_dir, slideshow_filename)
|
||
|
||
# 상대 경로로 변환
|
||
relative_paths = [os.path.relpath(path, output_dir) for path in image_paths]
|
||
|
||
html_content = f"""
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>Translation Results Slideshow</title>
|
||
<style>
|
||
body {{ font-family: Arial, sans-serif; margin: 0; padding: 20px; background: #f5f5f5; }}
|
||
.slideshow-container {{ position: relative; max-width: 1000px; margin: auto; background: white; }}
|
||
.slide {{ display: none; text-align: center; padding: 20px; }}
|
||
.slide.active {{ display: block; }}
|
||
.slide img {{ max-width: 100%; height: auto; }}
|
||
.prev, .next {{ cursor: pointer; position: absolute; top: 50%; width: auto; margin-top: -22px; padding: 16px; color: white; font-weight: bold; font-size: 18px; background: rgba(0,0,0,0.5); border: none; user-select: none; }}
|
||
.next {{ right: 0; }}
|
||
.prev:hover, .next:hover {{ background: rgba(0,0,0,0.8); }}
|
||
.dots-container {{ text-align: center; margin-top: 20px; }}
|
||
.dot {{ cursor: pointer; height: 15px; width: 15px; margin: 0 5px; background-color: #bbb; border-radius: 50%; display: inline-block; }}
|
||
.dot.active, .dot:hover {{ background-color: #717171; }}
|
||
.slide-counter {{ position: absolute; top: 10px; right: 10px; background: rgba(0,0,0,0.7); color: white; padding: 5px 10px; border-radius: 3px; }}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h1 style="text-align: center;">Translation Results Slideshow</h1>
|
||
|
||
<div class="slideshow-container">
|
||
"""
|
||
|
||
# 슬라이드 추가
|
||
for i, path in enumerate(relative_paths):
|
||
active_class = "active" if i == 0 else ""
|
||
html_content += f"""
|
||
<div class="slide {active_class}">
|
||
<div class="slide-counter">{i+1} / {len(relative_paths)}</div>
|
||
<img src="{path}" alt="Translation Result {i+1}">
|
||
</div>
|
||
"""
|
||
|
||
html_content += """
|
||
<button class="prev" onclick="changeSlide(-1)">❮</button>
|
||
<button class="next" onclick="changeSlide(1)">❯</button>
|
||
</div>
|
||
|
||
<div class="dots-container">
|
||
"""
|
||
|
||
# 도트 네비게이션 추가
|
||
for i in range(len(relative_paths)):
|
||
active_class = "active" if i == 0 else ""
|
||
html_content += f'<span class="dot {active_class}" onclick="currentSlide({i+1})"></span>'
|
||
|
||
html_content += """
|
||
</div>
|
||
|
||
<script>
|
||
let slideIndex = 1;
|
||
|
||
function changeSlide(n) {
|
||
showSlide(slideIndex += n);
|
||
}
|
||
|
||
function currentSlide(n) {
|
||
showSlide(slideIndex = n);
|
||
}
|
||
|
||
function showSlide(n) {
|
||
let slides = document.getElementsByClassName("slide");
|
||
let dots = document.getElementsByClassName("dot");
|
||
|
||
if (n > slides.length) {slideIndex = 1}
|
||
if (n < 1) {slideIndex = slides.length}
|
||
|
||
for (let i = 0; i < slides.length; i++) {
|
||
slides[i].classList.remove("active");
|
||
}
|
||
|
||
for (let i = 0; i < dots.length; i++) {
|
||
dots[i].classList.remove("active");
|
||
}
|
||
|
||
slides[slideIndex-1].classList.add("active");
|
||
dots[slideIndex-1].classList.add("active");
|
||
}
|
||
|
||
// 자동 슬라이드 (선택사항)
|
||
setInterval(function() {
|
||
changeSlide(1);
|
||
}, 10000); // 10초마다 자동 넘김
|
||
</script>
|
||
</body>
|
||
</html>
|
||
"""
|
||
|
||
with open(slideshow_path, 'w', encoding='utf-8') as f:
|
||
f.write(html_content)
|
||
|
||
print(f"슬라이드쇼 생성 완료: {slideshow_path}")
|
||
return slideshow_path
|
||
|
||
def test_module(self):
|
||
"""출력 모듈 테스트"""
|
||
print("출력 모듈 테스트 시작...")
|
||
|
||
# 테스트 출력 디렉토리 생성
|
||
test_output_dir = "test_output"
|
||
os.makedirs(test_output_dir, exist_ok=True)
|
||
|
||
# 테스트 이미지들 생성
|
||
original_image = self._create_test_image("Original Image", (0, 100, 0))
|
||
inpainted_image = self._create_test_image("Inpainted Image", (100, 0, 0))
|
||
final_image = self._create_test_image("Final Result", (0, 0, 100))
|
||
|
||
# 테스트 이미지 저장
|
||
original_path = os.path.join(test_output_dir, "test_original.jpg")
|
||
cv2.imwrite(original_path, original_image)
|
||
|
||
# 기본 비교 출력 테스트
|
||
print("기본 비교 출력 테스트...")
|
||
comparison_path = self.create_comparison_output(
|
||
original_path, inpainted_image, final_image,
|
||
test_output_dir, "cv2_telea"
|
||
)
|
||
|
||
# 상세 출력 테스트
|
||
print("상세 출력 테스트...")
|
||
test_ocr_results = [
|
||
{'text': '测试文本1', 'confidence': 0.95},
|
||
{'text': '测试文本2', 'confidence': 0.88}
|
||
]
|
||
test_translations = ['테스트 텍스트1', '테스트 텍스트2']
|
||
|
||
detail_path = self.create_detailed_output(
|
||
original_path, test_ocr_results, test_translations,
|
||
inpainted_image, final_image, test_output_dir, "lama"
|
||
)
|
||
|
||
print("출력 모듈 테스트 완료!")
|
||
print(f"테스트 결과는 {test_output_dir} 폴더에 저장되었습니다.")
|
||
|
||
def _create_test_image(self, text: str, color: Tuple[int, int, int]) -> np.ndarray:
|
||
"""테스트용 이미지 생성"""
|
||
image = np.ones((300, 400, 3), dtype=np.uint8) * 255
|
||
|
||
# 배경색 적용
|
||
image[:, :] = color
|
||
|
||
# 텍스트 추가
|
||
text_size = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 1, 2)[0]
|
||
text_x = (400 - text_size[0]) // 2
|
||
text_y = (300 + text_size[1]) // 2
|
||
|
||
cv2.putText(image, text, (text_x, text_y),
|
||
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
|
||
|
||
return image
|
||
|
||
if __name__ == "__main__":
|
||
output_module = OutputModule()
|
||
output_module.test_module() |