|
import os |
|
import sys |
|
import logging |
|
import replicate |
|
import gradio as gr |
|
from PIL import Image |
|
import tempfile |
|
import uuid |
|
|
|
|
|
logging.basicConfig( |
|
level=logging.INFO, |
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', |
|
handlers=[logging.StreamHandler(sys.stdout)] |
|
) |
|
logger = logging.getLogger("clarity-upscaler") |
|
|
|
|
|
REPLICATE_API_TOKEN = os.environ.get("REPLICATE_API_TOKEN", "") |
|
if not REPLICATE_API_TOKEN: |
|
logger.warning("REPLICATE_API_TOKEN์ด ์ค์ ๋์ง ์์์ต๋๋ค. ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํด์ฃผ์ธ์.") |
|
|
|
|
|
TEMP_DIR = os.path.join(tempfile.gettempdir(), "clarity_upscaler") |
|
os.makedirs(TEMP_DIR, exist_ok=True) |
|
logger.info(f"์์ ๋๋ ํ ๋ฆฌ ์์ฑ: {TEMP_DIR}") |
|
|
|
def upscale_image( |
|
image, |
|
scale_factor=2, |
|
output_format="jpg", |
|
sd_model="juggernaut_reborn.safetensors [338b85bc4f]", |
|
resemblance=0.6, |
|
creativity=0.35, |
|
prompt="masterpiece, best quality, highres, <lora:more_details:0.5> <lora:SDXLrender_v2.0:1>", |
|
negative_prompt="(worst quality, low quality, normal quality:2) JuggernautNegative-neg", |
|
seed=1337, |
|
dynamic=6, |
|
sharpen=0 |
|
): |
|
""" |
|
Clarity Upscaler๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง ํ์ง์ ๊ฐ์ ํฉ๋๋ค. |
|
|
|
Args: |
|
image: ์
๋ ฅ ์ด๋ฏธ์ง |
|
scale_factor: ํ๋ ๋น์จ (๊ธฐ๋ณธ๊ฐ: 2) |
|
output_format: ์ถ๋ ฅ ํ์ (๊ธฐ๋ณธ๊ฐ: jpg) |
|
sd_model: ์ฌ์ฉํ SD ๋ชจ๋ธ |
|
resemblance: ์๋ณธ๊ณผ์ ์ ์ฌ๋ (0.0-1.0) |
|
creativity: ์ฐฝ์์ฑ ์์ค (0.0-1.0) |
|
prompt: ์
์ค์ผ์ผ๋ง ๊ฐ์ด๋ ํ๋กฌํํธ |
|
negative_prompt: ๋ค๊ฑฐํฐ๋ธ ํ๋กฌํํธ |
|
seed: ๋๋ค ์๋ |
|
dynamic: ๋ค์ด๋๋ฏน ์๊ณ๊ฐ (1-10) |
|
sharpen: ์ ๋ช
๋ (0-2) |
|
|
|
Returns: |
|
๊ฐ์ ๋ ์ด๋ฏธ์ง |
|
""" |
|
if REPLICATE_API_TOKEN == "": |
|
raise ValueError("REPLICATE_API_TOKEN์ด ์ค์ ๋์ง ์์์ต๋๋ค.") |
|
|
|
try: |
|
|
|
temp_input_path = os.path.join(TEMP_DIR, f"input_{uuid.uuid4()}.png") |
|
image.save(temp_input_path) |
|
logger.info(f"์
๋ ฅ ์ด๋ฏธ์ง ์ ์ฅ: {temp_input_path}") |
|
|
|
|
|
replicate.client.Client(api_token=REPLICATE_API_TOKEN) |
|
|
|
|
|
logger.info("=== Clarity Upscaler ์คํ ์ ๋ณด ===") |
|
logger.info(f"๋ชจ๋ธ: philz1337x/clarity-upscaler") |
|
logger.info(f"SD ๋ชจ๋ธ: {sd_model}") |
|
logger.info(f"์ค์ผ์ผ ํฉํฐ: {scale_factor}") |
|
logger.info(f"์ถ๋ ฅ ํ์: {output_format}") |
|
logger.info(f"์ ์ฌ๋: {resemblance}") |
|
logger.info(f"์ฐฝ์์ฑ: {creativity}") |
|
logger.info(f"๋ค์ด๋๋ฏน: {dynamic}") |
|
logger.info(f"์ ๋ช
๋: {sharpen}") |
|
logger.info(f"์๋: {seed}") |
|
|
|
|
|
output = replicate.run( |
|
"philz1337x/clarity-upscaler:dfad41707589d68ecdccd1dfa600d55a208f9310748e44bfe35b4a6291453d5e", |
|
input={ |
|
"seed": seed, |
|
"image": open(temp_input_path, "rb"), |
|
"prompt": prompt, |
|
"dynamic": dynamic, |
|
"handfix": "disabled", |
|
"pattern": False, |
|
"sharpen": sharpen, |
|
"sd_model": sd_model, |
|
"scheduler": "DPM++ 3M SDE Karras", |
|
"creativity": creativity, |
|
"lora_links": "", |
|
"downscaling": False, |
|
"resemblance": resemblance, |
|
"scale_factor": scale_factor, |
|
"tiling_width": 112, |
|
"output_format": output_format, |
|
"tiling_height": 144, |
|
"custom_sd_model": "", |
|
"negative_prompt": negative_prompt, |
|
"num_inference_steps": 18, |
|
"downscaling_resolution": 768 |
|
} |
|
) |
|
|
|
logger.info(f"Replicate API ์๋ต: {output}") |
|
|
|
|
|
if output and isinstance(output, list) and len(output) > 0: |
|
import requests |
|
from io import BytesIO |
|
|
|
response = requests.get(output[0]) |
|
if response.status_code == 200: |
|
result_image = Image.open(BytesIO(response.content)) |
|
|
|
|
|
if output_format.lower() == "jpg": |
|
temp_output = BytesIO() |
|
if result_image.mode == 'RGBA': |
|
result_image = result_image.convert('RGB') |
|
result_image.save(temp_output, format='JPEG', quality=95) |
|
temp_output.seek(0) |
|
result_image = Image.open(temp_output) |
|
|
|
logger.info("์ด๋ฏธ์ง ํ์ง ๊ฐ์ ์๋ฃ!") |
|
return result_image |
|
else: |
|
logger.error(f"๊ฒฐ๊ณผ ์ด๋ฏธ์ง ๋ค์ด๋ก๋ ์คํจ: {response.status_code}") |
|
return None |
|
else: |
|
logger.error("API ์๋ต์์ ์ด๋ฏธ์ง๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.") |
|
return None |
|
|
|
except Exception as e: |
|
logger.error(f"ํ์ง ๊ฐ์ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}") |
|
raise |
|
finally: |
|
|
|
if os.path.exists(temp_input_path): |
|
os.remove(temp_input_path) |
|
|
|
|
|
def create_interface(): |
|
with gr.Blocks(title="Clarity Upscaler - ์ด๋ฏธ์ง ํ์ง ๊ฐ์ ") as demo: |
|
gr.Markdown("# Clarity Upscaler - ์ด๋ฏธ์ง ํ์ง ๊ฐ์ ๋๊ตฌ") |
|
gr.Markdown("Replicate์ Clarity Upscaler ๋ชจ๋ธ์ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง์ ํ์ง์ ๊ฐ์ ํฉ๋๋ค.") |
|
|
|
with gr.Row(): |
|
with gr.Column(): |
|
input_image = gr.Image(label="์๋ณธ ์ด๋ฏธ์ง", type="pil") |
|
|
|
with gr.Accordion("๊ณ ๊ธ ์ค์ ", open=False): |
|
scale_factor = gr.Slider(minimum=1, maximum=4, value=2, step=0.5, label="ํ๋ ๋น์จ") |
|
output_format = gr.Radio(["jpg", "png"], value="jpg", label="์ถ๋ ฅ ํ์") |
|
sd_model = gr.Dropdown( |
|
choices=[ |
|
"juggernaut_reborn.safetensors [338b85bc4f]", |
|
"sd_xl_base_1.0.safetensors [39d4e625d]", |
|
"sdxl_base_v0.9-9961.safetensors [3048045c]", |
|
"realisticVisionV51_v51VAE.safetensors [5ecbfa0ac]", |
|
], |
|
value="juggernaut_reborn.safetensors [338b85bc4f]", |
|
label="SD ๋ชจ๋ธ" |
|
) |
|
resemblance = gr.Slider(minimum=0.0, maximum=1.0, value=0.6, step=0.05, label="์๋ณธ ์ ์ฌ๋") |
|
creativity = gr.Slider(minimum=0.0, maximum=1.0, value=0.35, step=0.05, label="์ฐฝ์์ฑ") |
|
dynamic = gr.Slider(minimum=1, maximum=10, value=6, step=1, label="๋ค์ด๋๋ฏน ์๊ณ๊ฐ") |
|
sharpen = gr.Slider(minimum=0, maximum=2, value=0, step=0.1, label="์ ๋ช
๋") |
|
seed = gr.Number(value=1337, label="์๋", precision=0) |
|
|
|
submit_btn = gr.Button("ํ์ง ๊ฐ์ ์์", variant="primary") |
|
|
|
with gr.Column(): |
|
output_image = gr.Image(label="๊ฐ์ ๋ ์ด๋ฏธ์ง") |
|
log_output = gr.Textbox(label="๋ก๊ทธ", lines=10) |
|
|
|
|
|
class LogCapture: |
|
def __init__(self): |
|
self.logs = [] |
|
self.handler = self.create_handler() |
|
|
|
def create_handler(self): |
|
handler = logging.StreamHandler(stream=self) |
|
handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')) |
|
return handler |
|
|
|
def write(self, message): |
|
self.logs.append(message) |
|
|
|
def flush(self): |
|
pass |
|
|
|
def get_logs(self): |
|
return "".join(self.logs) |
|
|
|
def clear(self): |
|
self.logs.clear() |
|
|
|
log_capture = LogCapture() |
|
logger.addHandler(log_capture.handler) |
|
|
|
|
|
def process_image(image, scale_factor, output_format, sd_model, resemblance, creativity, dynamic, sharpen, seed): |
|
if image is None: |
|
return None, "์ค๋ฅ: ์ด๋ฏธ์ง๋ฅผ ์
๋ก๋ํด์ฃผ์ธ์." |
|
|
|
log_capture.clear() |
|
|
|
try: |
|
result = upscale_image( |
|
image=image, |
|
scale_factor=scale_factor, |
|
output_format=output_format, |
|
sd_model=sd_model, |
|
resemblance=resemblance, |
|
creativity=creativity, |
|
dynamic=dynamic, |
|
sharpen=sharpen, |
|
seed=int(seed) |
|
) |
|
return result, log_capture.get_logs() |
|
except Exception as e: |
|
logger.error(f"์ด๋ฏธ์ง ์ฒ๋ฆฌ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}") |
|
return None, log_capture.get_logs() |
|
|
|
submit_btn.click( |
|
process_image, |
|
inputs=[ |
|
input_image, scale_factor, output_format, sd_model, |
|
resemblance, creativity, dynamic, sharpen, seed |
|
], |
|
outputs=[output_image, log_output] |
|
) |
|
|
|
return demo |
|
|
|
|
|
if __name__ == "__main__": |
|
demo = create_interface() |
|
demo.launch(share=True) |