Update app.py
Browse files
app.py
CHANGED
@@ -1,2 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import os
|
2 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import replicate
|
3 |
+
from PIL import Image
|
4 |
+
import tempfile
|
5 |
+
import uuid
|
6 |
+
import requests
|
7 |
+
from io import BytesIO
|
8 |
import os
|
9 |
+
|
10 |
+
# 환경 변수에서 API 토큰, 비밀번호, 모델 이름들 가져오기
|
11 |
+
REPLICATE_API_TOKEN = os.getenv("REPLICATE_API_TOKEN")
|
12 |
+
PASSWORD = os.getenv("PASSWORD")
|
13 |
+
UPSCALER_MODEL = os.getenv("UPSCALER_MODEL")
|
14 |
+
TEXT_REMOVAL_MODEL = os.getenv("TEXT_REMOVAL_MODEL")
|
15 |
+
|
16 |
+
def upscale_image(image_path, output_format):
|
17 |
+
"""Clarity Upscaler를 사용하여 이미지 업스케일링 (모든 매개변수 고정)"""
|
18 |
+
try:
|
19 |
+
client = replicate.Client(api_token=REPLICATE_API_TOKEN)
|
20 |
+
|
21 |
+
with open(image_path, "rb") as file:
|
22 |
+
input_data = {
|
23 |
+
"image": file,
|
24 |
+
"scale_factor": 2, # 고정: 2배 확대
|
25 |
+
"resemblance": 0.8, # 고정: 높은 원본 유사도
|
26 |
+
"creativity": 0.2, # 고정: 낮은 창의성
|
27 |
+
"output_format": output_format.lower(),
|
28 |
+
"prompt": "high quality, detailed, sharp",
|
29 |
+
"negative_prompt": "(worst quality, low quality, normal quality:2)"
|
30 |
+
}
|
31 |
+
|
32 |
+
output = client.run(
|
33 |
+
UPSCALER_MODEL,
|
34 |
+
input=input_data
|
35 |
+
)
|
36 |
+
|
37 |
+
# 결과 이미지 다운로드
|
38 |
+
if output and isinstance(output, list) and len(output) > 0:
|
39 |
+
response = requests.get(output[0])
|
40 |
+
if response.status_code == 200:
|
41 |
+
result_image = Image.open(BytesIO(response.content))
|
42 |
+
|
43 |
+
# 임시 파일로 저장
|
44 |
+
ext = output_format.lower()
|
45 |
+
upscaled_filename = f"upscaled_temp_{uuid.uuid4()}.{ext}"
|
46 |
+
|
47 |
+
if ext == 'jpg' and result_image.mode == 'RGBA':
|
48 |
+
result_image = result_image.convert('RGB')
|
49 |
+
|
50 |
+
result_image.save(upscaled_filename, format='JPEG' if ext=='jpg' else 'PNG', quality=95 if ext=='jpg' else None)
|
51 |
+
|
52 |
+
return upscaled_filename
|
53 |
+
else:
|
54 |
+
return None
|
55 |
+
else:
|
56 |
+
return None
|
57 |
+
|
58 |
+
except Exception as e:
|
59 |
+
return None
|
60 |
+
|
61 |
+
def remove_text_from_image(input_image, password, output_format, upscale_option):
|
62 |
+
if not password:
|
63 |
+
return None, "비밀번호를 입력하세요.", None
|
64 |
+
|
65 |
+
if password != PASSWORD:
|
66 |
+
return None, "비밀번호가 올바르지 않습니다.", None
|
67 |
+
|
68 |
+
if input_image is None:
|
69 |
+
return None, "이미지를 업로드하세요.", None
|
70 |
+
|
71 |
+
try:
|
72 |
+
# Replicate 클라이언트 설정
|
73 |
+
client = replicate.Client(api_token=REPLICATE_API_TOKEN)
|
74 |
+
|
75 |
+
log_message = f"이미지 처리 시작...\n"
|
76 |
+
|
77 |
+
# Option 2: 로컬 파일 방식 사용
|
78 |
+
with open(input_image, "rb") as file:
|
79 |
+
input_file = file
|
80 |
+
|
81 |
+
log_message += f"파일 읽기 완료\n"
|
82 |
+
|
83 |
+
# Replicate API 호출 - output_format 매개변수 추가
|
84 |
+
input_data = {
|
85 |
+
"input_image": input_file,
|
86 |
+
"output_format": output_format # JPG 또는 PNG
|
87 |
+
}
|
88 |
+
|
89 |
+
log_message += f"텍스트 제거 API 호출 중... (출력 포맷: {output_format})\n"
|
90 |
+
|
91 |
+
output = client.run(
|
92 |
+
TEXT_REMOVAL_MODEL,
|
93 |
+
input=input_data
|
94 |
+
)
|
95 |
+
|
96 |
+
log_message += f"텍스트 제거 API 응답 수신 완료\n"
|
97 |
+
|
98 |
+
# 결과 이미지 처리
|
99 |
+
temp_filename = f"temp_output.{output_format.lower()}"
|
100 |
+
with open(temp_filename, "wb") as file:
|
101 |
+
file.write(output.read())
|
102 |
+
|
103 |
+
# 결과 이미지 로드
|
104 |
+
result_image = Image.open(temp_filename)
|
105 |
+
|
106 |
+
# 화질 개선 적용 (선택사항)
|
107 |
+
final_image = result_image
|
108 |
+
if upscale_option == "적용":
|
109 |
+
log_message += f"Clarity Upscaler로 화질 개선 시작... (2배 확대, 유사도: 0.8, 창의성: 0.2)\n"
|
110 |
+
upscaled_path = upscale_image(temp_filename, output_format)
|
111 |
+
|
112 |
+
if upscaled_path:
|
113 |
+
final_image = Image.open(upscaled_path)
|
114 |
+
log_message += f"화질 개선 완료\n"
|
115 |
+
else:
|
116 |
+
log_message += f"화질 개선 실패, 원본 이미지 사용\n"
|
117 |
+
|
118 |
+
# 다운로드용 파일명
|
119 |
+
download_filename = f"text_removed.{output_format.lower()}"
|
120 |
+
final_image.save(download_filename)
|
121 |
+
|
122 |
+
log_message += f"텍스트 제거 완료! (API에서 {output_format} 포맷으로 처리됨)"
|
123 |
+
|
124 |
+
return final_image, log_message, download_filename
|
125 |
+
|
126 |
+
except Exception as e:
|
127 |
+
error_message = f"오류 발생: {str(e)}"
|
128 |
+
return None, error_message, None
|
129 |
+
|
130 |
+
# Gradio 인터페이스
|
131 |
+
with gr.Blocks() as demo:
|
132 |
+
with gr.Row():
|
133 |
+
with gr.Column():
|
134 |
+
input_image = gr.Image(type="filepath", label="입력 이미지")
|
135 |
+
api_password = gr.Textbox(
|
136 |
+
label="비밀번호",
|
137 |
+
type="password"
|
138 |
+
)
|
139 |
+
output_format = gr.Radio(
|
140 |
+
choices=["jpg", "png"],
|
141 |
+
value="jpg",
|
142 |
+
label="출력 포맷"
|
143 |
+
)
|
144 |
+
upscale_option = gr.Radio(
|
145 |
+
choices=["없음", "적용"],
|
146 |
+
value="없음",
|
147 |
+
label="화질 개선 (2배 확대)"
|
148 |
+
)
|
149 |
+
submit_btn = gr.Button("텍스트 제거", variant="primary")
|
150 |
+
|
151 |
+
with gr.Column():
|
152 |
+
output_image = gr.Image(label="처리된 이미지")
|
153 |
+
log_output = gr.Textbox(label="로그", lines=10, max_lines=15)
|
154 |
+
download_file = gr.File(label="다운로드")
|
155 |
+
|
156 |
+
submit_btn.click(
|
157 |
+
fn=remove_text_from_image,
|
158 |
+
inputs=[input_image, api_password, output_format, upscale_option],
|
159 |
+
outputs=[output_image, log_output, download_file]
|
160 |
+
)
|
161 |
+
|
162 |
+
if __name__ == "__main__":
|
163 |
+
demo.launch()
|