188 lines
7.3 KiB
Python
188 lines
7.3 KiB
Python
import os
|
|
import re
|
|
import sys
|
|
import ast
|
|
import json
|
|
import cv2
|
|
import numpy as np
|
|
|
|
#사용법
|
|
|
|
# ./Scripts/python.exe -X utf8 test/server_inpaint_smoke.py --image D:\py\AutoPercenty3_311\src\temp_images\detail_image_000_O1CN016JhqPc28B31bgShOk_!!3823937893_resized.jpg_Q75_resized.jpg
|
|
|
|
|
|
def _project_root():
|
|
here = os.path.abspath(os.path.dirname(__file__))
|
|
return os.path.abspath(os.path.join(here, '..'))
|
|
|
|
|
|
def parse_case_from_log(log_path: str, target_image: str | None = None):
|
|
"""Edit_PartTimer3.log 에서 마지막 케이스의
|
|
- 로컬 이미지 경로
|
|
- filter_ocr_results (polygon 포함)
|
|
- 요청 인페인트 서버 URL
|
|
을 추출한다.
|
|
"""
|
|
image_path = None
|
|
ocr_results = None
|
|
inpaint_endpoint = None
|
|
|
|
if not os.path.exists(log_path):
|
|
raise FileNotFoundError(f'로그 파일을 찾을 수 없음: {log_path}')
|
|
|
|
with open(log_path, 'r', encoding='utf-8', errors='ignore') as f:
|
|
lines = f.readlines()
|
|
|
|
def _parse_block(start_idx: int):
|
|
nonlocal image_path, ocr_results, inpaint_endpoint
|
|
# 앞/뒤 모두에서 찾을 수 있으니 주변에서 스캔
|
|
for i in range(start_idx, min(start_idx + 800, len(lines))):
|
|
line = lines[i]
|
|
if ocr_results is None and 'filter_ocr_results:' in line:
|
|
try:
|
|
txt = line.split('filter_ocr_results:', 1)[1].strip()
|
|
ocr_results = ast.literal_eval(txt)
|
|
except Exception:
|
|
buf = [line.split('filter_ocr_results:', 1)[1]]
|
|
j = i + 1
|
|
while j < len(lines) and ']' not in ''.join(buf):
|
|
buf.append(lines[j])
|
|
j += 1
|
|
try:
|
|
ocr_results = ast.literal_eval(''.join(buf))
|
|
except Exception:
|
|
pass
|
|
if inpaint_endpoint is None and '요청 인페인팅 서버 :' in line:
|
|
ep = line.split('요청 인페인팅 서버 :', 1)[1].strip()
|
|
inpaint_endpoint = ep.split()[0]
|
|
if ocr_results is not None and inpaint_endpoint:
|
|
break
|
|
|
|
if target_image:
|
|
# 정확히 해당 이미지 경로를 포함한 라인을 찾음
|
|
target_idx = None
|
|
for i, line in enumerate(lines):
|
|
if target_image in line:
|
|
target_idx = i
|
|
if target_idx is None:
|
|
raise RuntimeError(f'지정한 이미지 경로를 로그에서 찾을 수 없음: {target_image}')
|
|
image_path = target_image
|
|
_parse_block(target_idx)
|
|
else:
|
|
# 뒤에서부터 스캔하여 마지막 케이스 사용
|
|
for i in range(len(lines) - 1, -1, -1):
|
|
line = lines[i]
|
|
if image_path is None:
|
|
m = re.search(r'로컬 저장위치\(.*\):\s*(.+)$', line)
|
|
if m:
|
|
image_path = m.group(1).strip()
|
|
continue
|
|
if ocr_results is None and 'filter_ocr_results:' in line:
|
|
try:
|
|
txt = line.split('filter_ocr_results:', 1)[1].strip()
|
|
ocr_results = ast.literal_eval(txt)
|
|
except Exception:
|
|
buf = [line.split('filter_ocr_results:', 1)[1]]
|
|
j = i + 1
|
|
while j < len(lines) and ']' not in ''.join(buf):
|
|
buf.append(lines[j])
|
|
j += 1
|
|
try:
|
|
ocr_results = ast.literal_eval(''.join(buf))
|
|
except Exception:
|
|
pass
|
|
continue
|
|
if inpaint_endpoint is None and '요청 인페인팅 서버 :' in line:
|
|
ep = line.split('요청 인페인팅 서버 :', 1)[1].strip()
|
|
inpaint_endpoint = ep.split()[0]
|
|
continue
|
|
if image_path and ocr_results is not None and inpaint_endpoint:
|
|
break
|
|
|
|
if not image_path:
|
|
raise RuntimeError('로그에서 로컬 이미지 경로를 찾지 못했습니다.')
|
|
if ocr_results is None:
|
|
raise RuntimeError('로그에서 filter_ocr_results 를 찾지 못했습니다.')
|
|
|
|
# endpoint 가 전체 경로(/api/v1/inpaint 포함)라면 그대로 사용
|
|
return image_path, ocr_results, inpaint_endpoint
|
|
|
|
|
|
def build_mask(image_path: str, ocr_results: list, expansion_size: int = 9, blur_size: int = 12):
|
|
# 모듈 임포트 경로 설정
|
|
sys.path.append(_project_root())
|
|
from src.modules.mask_module_for_paddle import MaskModule
|
|
|
|
class _DummyLogger:
|
|
def log(self, msg, level=None, exc_info=False):
|
|
print(msg)
|
|
|
|
mm = MaskModule(logger=_DummyLogger(), base_dir=_project_root())
|
|
mask = mm.create_masks(
|
|
image_path=image_path,
|
|
ocr_results=ocr_results,
|
|
mask_option='basic',
|
|
expansion_size=expansion_size,
|
|
blur_size=blur_size,
|
|
)
|
|
return mask
|
|
|
|
|
|
def request_inpaint(endpoint: str, image_path: str, mask: np.ndarray, invert_mask: bool = False, save_path: str = None):
|
|
sys.path.append(_project_root())
|
|
from src.modules.request_inpaint import Request_AI_Server
|
|
|
|
class _DummyLogger:
|
|
def log(self, msg, level=None, exc_info=False):
|
|
print(msg)
|
|
|
|
# endpoint 가 /api/v1/inpaint 까지 포함되어 오면 base_url 을 잘라낸다
|
|
base_url = endpoint
|
|
if '/api/v1/inpaint' in endpoint:
|
|
base_url = endpoint.split('/api/v1/inpaint', 1)[0]
|
|
|
|
client = Request_AI_Server(logger=_DummyLogger(), inpaint_server_url=base_url)
|
|
result = client.request_inpaint(image_path, mask, invert_mask=invert_mask)
|
|
if result is not None and save_path:
|
|
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
|
cv2.imwrite(save_path, result)
|
|
return result
|
|
|
|
|
|
def main():
|
|
import argparse
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument('--image', type=str, default=None, help='테스트할 원본 이미지 경로(로그에 존재해야 함)')
|
|
ap.add_argument('--invert', action='store_true', help='반전 only 단일 테스트')
|
|
args = ap.parse_args()
|
|
root = _project_root()
|
|
log_path = os.path.join(root, 'src', 'logs', 'Edit_PartTimer3.log')
|
|
debug_dir = os.path.join(root, 'src', 'debug_images')
|
|
os.makedirs(debug_dir, exist_ok=True)
|
|
|
|
image_path, ocr_results, endpoint = parse_case_from_log(log_path, target_image=args.image)
|
|
print('[SMOKE] image_path =', image_path)
|
|
print('[SMOKE] endpoint =', endpoint)
|
|
print('[SMOKE] ocr count =', len(ocr_results))
|
|
|
|
mask = build_mask(image_path, ocr_results)
|
|
mask_path = os.path.join(debug_dir, 'smoke_mask.png')
|
|
cv2.imwrite(mask_path, (mask > 0).astype(np.uint8) * 255)
|
|
print('[SMOKE] mask saved =', mask_path)
|
|
|
|
if args.invert:
|
|
out_path = os.path.join(debug_dir, 'smoke_inpaint_invert_1.png')
|
|
res = request_inpaint(endpoint, image_path, mask, invert_mask=True, save_path=out_path)
|
|
print(f'[SMOKE] invert=True →', 'OK' if res is not None else 'FAILED', '→', out_path)
|
|
else:
|
|
for invert in (False, True):
|
|
out_path = os.path.join(debug_dir, f'smoke_inpaint_invert_{int(invert)}.png')
|
|
res = request_inpaint(endpoint, image_path, mask, invert_mask=invert, save_path=out_path)
|
|
print(f'[SMOKE] invert={invert} →', 'OK' if res is not None else 'FAILED', '→', out_path)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
|
|
|