Update app.py
Browse files
app.py
CHANGED
|
@@ -1,2 +1,938 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import os
|
| 2 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import numpy as np
|
| 3 |
+
from PIL import Image, ImageEnhance
|
| 4 |
+
import random
|
| 5 |
+
import cv2
|
| 6 |
+
import io
|
| 7 |
+
import datetime
|
| 8 |
+
import zipfile
|
| 9 |
+
import tempfile
|
| 10 |
import os
|
| 11 |
+
import shutil
|
| 12 |
+
import pytz
|
| 13 |
+
import logging
|
| 14 |
+
|
| 15 |
+
# ------------------- ๋ก๊น
์ค์ -------------------
|
| 16 |
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 17 |
+
logger = logging.getLogger(__name__)
|
| 18 |
+
|
| 19 |
+
class ImageTransformer:
|
| 20 |
+
def __init__(self):
|
| 21 |
+
self.method_info = {
|
| 22 |
+
"๋ฏธ์ธ ๋
ธ์ด์ฆ ์ถ๊ฐ": {
|
| 23 |
+
"function": self.add_micro_noise,
|
| 24 |
+
"description": "์ด๋ฏธ์ง์ ๋์ ๋ณด์ด์ง ์๋ ์์ ๋
ธ์ด์ฆ๋ฅผ ์ถ๊ฐํฉ๋๋ค. ํฝ์
๊ฐ์ 0.1~0.5 ์ ๋์ ๋ฏธ์ธํ ๋ณํ๋ฅผ ์ค๋๋ค."
|
| 25 |
+
},
|
| 26 |
+
"์์ ๋ฏธ์ธ ์กฐ์ ": {
|
| 27 |
+
"function": self.adjust_color_slightly,
|
| 28 |
+
"description": "์ด๋ฏธ์ง์ ์ฑ๋์ ์์กฐ๋ฅผ ์์ฃผ ์กฐ๊ธ ๋ณ๊ฒฝํฉ๋๋ค. ์ฌ๋ ๋์ผ๋ก๋ ๊ตฌ๋ถ์ด ์ด๋ ค์ด 0.1% ์ด๋ด์ ๋ณํ์
๋๋ค."
|
| 29 |
+
},
|
| 30 |
+
"๋ฏธ์ธ ํ์ ": {
|
| 31 |
+
"function": self.micro_rotate,
|
| 32 |
+
"description": "์ด๋ฏธ์ง๋ฅผ 0.1๋ ์ด๋ด๋ก ํ์ ์ํต๋๋ค. ์ก์์ผ๋ก๋ ํ์ ์ ๊ฐ์งํ ์ ์๋ ์์ค์
๋๋ค."
|
| 33 |
+
},
|
| 34 |
+
"๋ฏธ์ธ ํฌ๊ธฐ ์กฐ์ ": {
|
| 35 |
+
"function": self.micro_scale,
|
| 36 |
+
"description": "์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ 0.01% ์ ๋ ๋ณ๊ฒฝํ๋ค๊ฐ ๋ค์ ์๋ ํฌ๊ธฐ๋ก ๋ณต์ํฉ๋๋ค. ํฝ์
๋ณด๊ฐ์ผ๋ก ์ธํ ๋ฏธ์ธํ ์ฐจ์ด๊ฐ ๋ฐ์ํฉ๋๋ค."
|
| 37 |
+
},
|
| 38 |
+
"์์ถ๋ฅ ์กฐ์ ": {
|
| 39 |
+
"function": self.adjust_compression,
|
| 40 |
+
"description": "JPEG ์์ถ ํ์ง์ 94-96 ์ฌ์ด์์ ๋๋คํ๊ฒ ๋ณ๊ฒฝํฉ๋๋ค. ํ์ง ์ฐจ์ด๋ ๊ฑฐ์ ์์ง๋ง ํ์ผ ๊ตฌ์กฐ๊ฐ ๋ฌ๋ผ์ง๋๋ค."
|
| 41 |
+
},
|
| 42 |
+
"๋ณด์ด์ง ์๋ ์ํฐ๋งํฌ": {
|
| 43 |
+
"function": self.add_invisible_watermark,
|
| 44 |
+
"description": "๋์ ๋ณด์ด์ง ์๋ ํจํด์ ์ด๋ฏธ์ง์ ์ถ๊ฐํฉ๋๋ค. 0.1~0.3 ์ ๋์ ๋งค์ฐ ์ฝํ ๊ฒฉ์ ํจํด์
๋๋ค."
|
| 45 |
+
},
|
| 46 |
+
"๋ฐ๊ธฐ/๋๋น ๋ฏธ์ธ ์กฐ์ ": {
|
| 47 |
+
"function": self.micro_brightness_contrast,
|
| 48 |
+
"description": "๋ฐ๊ธฐ์ ๋๋น๋ฅผ 0.1% ์ด๋ด๋ก ์กฐ์ ํฉ๋๋ค. ๋ชจ๋ํฐ ์ค์ ์ฐจ์ด๋ณด๋ค ์์ ๋ณํ์
๋๋ค."
|
| 49 |
+
},
|
| 50 |
+
"ํฝ์
์์น ๋ฏธ์ธ ์ด๋": {
|
| 51 |
+
"function": self.pixel_shift,
|
| 52 |
+
"description": "์ ์ฒด ์ด๋ฏธ์ง๋ฅผ 0.5ํฝ์
์ด๋ด๋ก ์ด๋์ํต๋๋ค. ์๋ธํฝ์
๋จ์์ ์ด๋์ผ๋ก ์ก์ ๊ตฌ๋ถ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค."
|
| 53 |
+
},
|
| 54 |
+
"์ฑ๋๋ณ ๋ฏธ์ธ ์กฐ์ ": {
|
| 55 |
+
"function": self.channel_adjustment,
|
| 56 |
+
"description": "RGB ๊ฐ ์ฑ๋์ ๊ฐ์ ยฑ1 ์ ๋ ์กฐ์ ํฉ๋๋ค. ์์ ์ฐจ์ด๊ฐ ๊ฑฐ์ ์์ง๋ง ๋ฐ์ดํฐ๋ ๋ค๋ฆ
๋๋ค."
|
| 57 |
+
},
|
| 58 |
+
"๋ฏธ์ธ ๋ธ๋ฌ ํจ๊ณผ": {
|
| 59 |
+
"function": self.micro_blur,
|
| 60 |
+
"description": "์ด๋ฏธ์ง์ ์์ฃผ ์ฝํ ๋ธ๋ฌ ํจ๊ณผ๋ฅผ ์ ์ฉํฉ๋๋ค. ์ ๋ช
๋ ์ฐจ์ด๋ฅผ ๊ฑฐ์ ๋๋ ์ ์๋ ์์ค์
๋๋ค."
|
| 61 |
+
}
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
def add_micro_noise(self, img_array, intensity=0.5):
|
| 65 |
+
"""๊ทน๋ฏธ๋์ ๊ฐ์ฐ์์ ๋
ธ์ด์ฆ ์ถ๊ฐ"""
|
| 66 |
+
img_float = img_array.astype(np.float32)
|
| 67 |
+
noise = np.random.normal(0, intensity * 5, img_array.shape)
|
| 68 |
+
noisy_image = img_float + noise
|
| 69 |
+
return np.clip(noisy_image, 0, 255).astype(np.uint8)
|
| 70 |
+
|
| 71 |
+
def adjust_color_slightly(self, img_array, intensity=0.5):
|
| 72 |
+
"""์์์ ๋ฏธ์ธํ๊ฒ ์กฐ์ """
|
| 73 |
+
img_pil = Image.fromarray(img_array)
|
| 74 |
+
enhancer = ImageEnhance.Color(img_pil)
|
| 75 |
+
factor = 1.0 + (random.uniform(-0.02, 0.02) * intensity)
|
| 76 |
+
img_pil = enhancer.enhance(factor)
|
| 77 |
+
return np.array(img_pil)
|
| 78 |
+
|
| 79 |
+
def micro_rotate(self, img_array, intensity=0.5):
|
| 80 |
+
"""๋ฏธ์ธํ ํ์ ์ ์ฉ"""
|
| 81 |
+
angle = random.uniform(-0.5, 0.5) * intensity
|
| 82 |
+
rows, cols = img_array.shape[:2]
|
| 83 |
+
M = cv2.getRotationMatrix2D((cols/2, rows/2), angle, 1)
|
| 84 |
+
rotated = cv2.warpAffine(img_array, M, (cols, rows),
|
| 85 |
+
borderMode=cv2.BORDER_REFLECT)
|
| 86 |
+
return rotated
|
| 87 |
+
|
| 88 |
+
def micro_scale(self, img_array, intensity=0.5):
|
| 89 |
+
"""๋ฏธ์ธํ ํฌ๊ธฐ ์กฐ์ """
|
| 90 |
+
scale_factor = 1.0 + (random.uniform(-0.002, 0.002) * intensity)
|
| 91 |
+
rows, cols = img_array.shape[:2]
|
| 92 |
+
new_rows, new_cols = int(rows * scale_factor), int(cols * scale_factor)
|
| 93 |
+
resized = cv2.resize(img_array, (new_cols, new_rows),
|
| 94 |
+
interpolation=cv2.INTER_LANCZOS4)
|
| 95 |
+
final = cv2.resize(resized, (cols, rows),
|
| 96 |
+
interpolation=cv2.INTER_LANCZOS4)
|
| 97 |
+
return final
|
| 98 |
+
|
| 99 |
+
def adjust_compression(self, img_array, intensity=0.5):
|
| 100 |
+
"""์์ถ๋ฅ ๋ฏธ์ธ ์กฐ์ """
|
| 101 |
+
img_pil = Image.fromarray(img_array)
|
| 102 |
+
buffer = io.BytesIO()
|
| 103 |
+
quality = int(95 - (random.uniform(3, 8) * intensity))
|
| 104 |
+
img_pil.save(buffer, format='JPEG', quality=quality)
|
| 105 |
+
buffer.seek(0)
|
| 106 |
+
compressed_img = Image.open(buffer)
|
| 107 |
+
return np.array(compressed_img)
|
| 108 |
+
|
| 109 |
+
def add_invisible_watermark(self, img_array, intensity=0.5):
|
| 110 |
+
"""๋์ ๋ณด์ด์ง ์๋ ๋ฏธ์ธํ ์ํฐ๋งํฌ ์ถ๊ฐ"""
|
| 111 |
+
rows, cols = img_array.shape[:2]
|
| 112 |
+
watermark = np.zeros((rows, cols), dtype=np.float32)
|
| 113 |
+
for i in range(0, rows, 20):
|
| 114 |
+
for j in range(0, cols, 20):
|
| 115 |
+
if random.random() > 0.5:
|
| 116 |
+
watermark[i, j] = 2.0 * intensity
|
| 117 |
+
watermark = cv2.GaussianBlur(watermark, (5, 5), 0)
|
| 118 |
+
if len(img_array.shape) == 3:
|
| 119 |
+
watermark = np.dstack([watermark] * 3)
|
| 120 |
+
|
| 121 |
+
img_float = img_array.astype(np.float32)
|
| 122 |
+
watermarked = img_float + watermark
|
| 123 |
+
return np.clip(watermarked, 0, 255).astype(np.uint8)
|
| 124 |
+
|
| 125 |
+
def micro_brightness_contrast(self, img_array, intensity=0.5):
|
| 126 |
+
"""๋ฐ๊ธฐ์ ๋๋น ๋ฏธ์ธ ์กฐ์ """
|
| 127 |
+
alpha = 1.0 + (random.uniform(-0.01, 0.01) * intensity)
|
| 128 |
+
beta = random.uniform(-3, 3) * intensity
|
| 129 |
+
adjusted = cv2.convertScaleAbs(img_array, alpha=alpha, beta=beta)
|
| 130 |
+
return adjusted
|
| 131 |
+
|
| 132 |
+
def pixel_shift(self, img_array, intensity=0.5):
|
| 133 |
+
"""ํฝ์
์์น ๋ฏธ์ธ ์ด๋"""
|
| 134 |
+
rows, cols = img_array.shape[:2]
|
| 135 |
+
dx = random.uniform(-2.0, 2.0) * intensity
|
| 136 |
+
dy = random.uniform(-2.0, 2.0) * intensity
|
| 137 |
+
M = np.float32([[1, 0, dx], [0, 1, dy]])
|
| 138 |
+
shifted = cv2.warpAffine(img_array, M, (cols, rows),
|
| 139 |
+
borderMode=cv2.BORDER_REFLECT)
|
| 140 |
+
return shifted
|
| 141 |
+
|
| 142 |
+
def channel_adjustment(self, img_array, intensity=0.5):
|
| 143 |
+
"""์ฑ๋๋ณ ๋ฏธ์ธ ์กฐ์ """
|
| 144 |
+
adjusted = img_array.astype(np.float32)
|
| 145 |
+
for i in range(3):
|
| 146 |
+
adjustment = random.randint(-4, 4) * intensity
|
| 147 |
+
adjusted[:, :, i] = adjusted[:, :, i] + adjustment
|
| 148 |
+
|
| 149 |
+
adjusted = np.clip(adjusted, 0, 255)
|
| 150 |
+
return adjusted.astype(np.uint8)
|
| 151 |
+
|
| 152 |
+
def micro_blur(self, img_array, intensity=0.5):
|
| 153 |
+
"""๋ฏธ์ธ ๋ธ๋ฌ ํจ๊ณผ"""
|
| 154 |
+
kernel_size = 3
|
| 155 |
+
sigma = 0.5 * intensity
|
| 156 |
+
blurred = cv2.GaussianBlur(img_array, (kernel_size, kernel_size), sigma)
|
| 157 |
+
return blurred
|
| 158 |
+
|
| 159 |
+
def transform_image_with_details(self, image, selected_methods, intensity):
|
| 160 |
+
"""์ด๋ฏธ์ง ๋ณํ ๋ฐ ์์ธ ์ ๋ณด ๋ฐํ"""
|
| 161 |
+
if image is None:
|
| 162 |
+
return None, {}
|
| 163 |
+
|
| 164 |
+
img_array = np.array(image)
|
| 165 |
+
details = {}
|
| 166 |
+
|
| 167 |
+
for method_name in selected_methods:
|
| 168 |
+
if method_name in self.method_info:
|
| 169 |
+
if method_name == "๋ฏธ์ธ ๋
ธ์ด์ฆ ์ถ๊ฐ":
|
| 170 |
+
noise_level = intensity * 5
|
| 171 |
+
img_array = self.add_micro_noise(img_array, intensity)
|
| 172 |
+
details[method_name] = f"๊ฐ์ฐ์์ ๋
ธ์ด์ฆ ๊ฐ๋: {noise_level:.3f} (ํ์คํธ์ฐจ)"
|
| 173 |
+
|
| 174 |
+
elif method_name == "์์ ๋ฏธ์ธ ์กฐ์ ":
|
| 175 |
+
factor_change = random.uniform(-0.02, 0.02) * intensity
|
| 176 |
+
img_array = self.adjust_color_slightly(img_array, intensity)
|
| 177 |
+
details[method_name] = f"์ฑ๋ ๋ณํ: {factor_change*100:.2f}%"
|
| 178 |
+
|
| 179 |
+
elif method_name == "๋ฏธ์ธ ํ์ ":
|
| 180 |
+
angle = random.uniform(-0.5, 0.5) * intensity
|
| 181 |
+
img_array = self.micro_rotate(img_array, intensity)
|
| 182 |
+
details[method_name] = f"ํ์ ๊ฐ๋: {angle:.3f}๋"
|
| 183 |
+
|
| 184 |
+
elif method_name == "๋ฏธ์ธ ํฌ๊ธฐ ์กฐ์ ":
|
| 185 |
+
scale_change = random.uniform(-0.002, 0.002) * intensity
|
| 186 |
+
img_array = self.micro_scale(img_array, intensity)
|
| 187 |
+
details[method_name] = f"ํฌ๊ธฐ ๋ณํ: {scale_change*100:.3f}%"
|
| 188 |
+
|
| 189 |
+
elif method_name == "์์ถ๋ฅ ์กฐ์ ":
|
| 190 |
+
quality_reduction = random.uniform(3, 8) * intensity
|
| 191 |
+
quality = int(95 - quality_reduction)
|
| 192 |
+
img_array = self.adjust_compression(img_array, intensity)
|
| 193 |
+
details[method_name] = f"JPEG ํ์ง: {quality} (์๋ณธ ๋๋น -{quality_reduction:.1f})"
|
| 194 |
+
|
| 195 |
+
elif method_name == "๋ณด์ด์ง ์๋ ์ํฐ๋งํฌ":
|
| 196 |
+
pattern_intensity = 2.0 * intensity
|
| 197 |
+
img_array = self.add_invisible_watermark(img_array, intensity)
|
| 198 |
+
details[method_name] = f"ํจํด ๊ฐ๋: {pattern_intensity:.2f} (20x20 ๊ทธ๋ฆฌ๋)"
|
| 199 |
+
|
| 200 |
+
elif method_name == "๋ฐ๊ธฐ/๋๋น ๋ฏธ์ธ ์กฐ์ ":
|
| 201 |
+
alpha_change = random.uniform(-0.01, 0.01) * intensity
|
| 202 |
+
beta_change = random.uniform(-3, 3) * intensity
|
| 203 |
+
img_array = self.micro_brightness_contrast(img_array, intensity)
|
| 204 |
+
details[method_name] = f"๋๋น ๋ณํ: {alpha_change*100:.2f}%, ๋ฐ๊ธฐ ๋ณํ: {beta_change:.2f}"
|
| 205 |
+
|
| 206 |
+
elif method_name == "ํฝ์
์์น ๋ฏธ์ธ ์ด๋":
|
| 207 |
+
dx = random.uniform(-2.0, 2.0) * intensity
|
| 208 |
+
dy = random.uniform(-2.0, 2.0) * intensity
|
| 209 |
+
img_array = self.pixel_shift(img_array, intensity)
|
| 210 |
+
details[method_name] = f"์ด๋๋: X์ถ {dx:.2f}px, Y์ถ {dy:.2f}px"
|
| 211 |
+
|
| 212 |
+
elif method_name == "์ฑ๋๋ณ ๋ฏธ์ธ ์กฐ์ ":
|
| 213 |
+
rgb_changes = [random.randint(-4, 4) * intensity for _ in range(3)]
|
| 214 |
+
img_array = self.channel_adjustment(img_array, intensity)
|
| 215 |
+
details[method_name] = f"RGB ์กฐ์ : R{rgb_changes[0]:+.1f}, G{rgb_changes[1]:+.1f}, B{rgb_changes[2]:+.1f}"
|
| 216 |
+
|
| 217 |
+
elif method_name == "๋ฏธ์ธ ๋ธ๋ฌ ํจ๊ณผ":
|
| 218 |
+
sigma = 0.5 * intensity
|
| 219 |
+
img_array = self.micro_blur(img_array, intensity)
|
| 220 |
+
details[method_name] = f"๋ธ๋ฌ ๊ฐ๋(์๊ทธ๋ง): {sigma:.3f}"
|
| 221 |
+
|
| 222 |
+
transformed_image = Image.fromarray(img_array)
|
| 223 |
+
|
| 224 |
+
# EXIF ๋ฐ์ดํฐ ์ฒ๋ฆฌ (์๋ฌ ๋ฐฉ์ง)
|
| 225 |
+
try:
|
| 226 |
+
exif = transformed_image.getexif()
|
| 227 |
+
exif[0x9003] = datetime.datetime.now().strftime("%Y:%m:%d %H:%M:%S")
|
| 228 |
+
except:
|
| 229 |
+
pass
|
| 230 |
+
|
| 231 |
+
return transformed_image, details
|
| 232 |
+
|
| 233 |
+
def calculate_similarity(self, original, transformed):
|
| 234 |
+
"""์๋ณธ๊ณผ ๋ณํ๋ ์ด๋ฏธ์ง์ ์ ์ฌ๋ ๊ณ์ฐ"""
|
| 235 |
+
if original is None or transformed is None:
|
| 236 |
+
return 0.0
|
| 237 |
+
|
| 238 |
+
original_cv = cv2.cvtColor(np.array(original), cv2.COLOR_RGB2BGR)
|
| 239 |
+
transformed_cv = cv2.cvtColor(np.array(transformed), cv2.COLOR_RGB2BGR)
|
| 240 |
+
|
| 241 |
+
# MSE ๊ธฐ๋ฐ ์ ์ฌ๋ ๊ณ์ฐ
|
| 242 |
+
mse = np.mean((original_cv - transformed_cv) ** 2)
|
| 243 |
+
if mse == 0:
|
| 244 |
+
return 100.0
|
| 245 |
+
|
| 246 |
+
# MSE๋ฅผ ๋ ๋ฏผ๊ฐํ๊ฒ ๋ฐ์ํ๋๋ก ์กฐ์
|
| 247 |
+
max_mse = 255.0 * 255.0
|
| 248 |
+
similarity = 100 - (mse / max_mse * 100 * 5)
|
| 249 |
+
|
| 250 |
+
return max(85, min(95, similarity))
|
| 251 |
+
|
| 252 |
+
# ๋คํฌ๋ชจ๋ ์ง์ ์ปค์คํ
CSS ์คํ์ผ
|
| 253 |
+
custom_css = """
|
| 254 |
+
/* ============================================
|
| 255 |
+
1. CSS ๋ณ์ ์ ์ (๋ผ์ดํธ๋ชจ๋ - ๊ธฐ๋ณธ๊ฐ)
|
| 256 |
+
============================================ */
|
| 257 |
+
:root {
|
| 258 |
+
/* ๋ฉ์ธ ์ปฌ๋ฌ */
|
| 259 |
+
--primary-color: #FB7F0D;
|
| 260 |
+
--secondary-color: #ff9a8b;
|
| 261 |
+
--accent-color: #FF6B6B;
|
| 262 |
+
|
| 263 |
+
/* ๋ฐฐ๊ฒฝ ์ปฌ๋ฌ */
|
| 264 |
+
--background-color: #FFFFFF;
|
| 265 |
+
--card-bg: #ffffff;
|
| 266 |
+
--input-bg: #ffffff;
|
| 267 |
+
|
| 268 |
+
/* ํ
์คํธ ์ปฌ๋ฌ */
|
| 269 |
+
--text-color: #334155;
|
| 270 |
+
--text-secondary: #64748b;
|
| 271 |
+
|
| 272 |
+
/* ๋ณด๋ ๋ฐ ๊ตฌ๋ถ์ */
|
| 273 |
+
--border-color: #dddddd;
|
| 274 |
+
--border-light: #e5e5e5;
|
| 275 |
+
|
| 276 |
+
/* ํ
์ด๋ธ ์ปฌ๋ฌ */
|
| 277 |
+
--table-even-bg: #f3f3f3;
|
| 278 |
+
--table-hover-bg: #f0f0f0;
|
| 279 |
+
|
| 280 |
+
/* ๊ทธ๋ฆผ์ */
|
| 281 |
+
--shadow: 0 8px 30px rgba(251, 127, 13, 0.08);
|
| 282 |
+
--shadow-light: 0 2px 4px rgba(0, 0, 0, 0.1);
|
| 283 |
+
|
| 284 |
+
/* ๊ธฐํ */
|
| 285 |
+
--border-radius: 18px;
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
/* ============================================
|
| 289 |
+
2. ๋คํฌ๋ชจ๋ ์์ ๋ณ์ (์๋ ๊ฐ์ง)
|
| 290 |
+
============================================ */
|
| 291 |
+
@media (prefers-color-scheme: dark) {
|
| 292 |
+
:root {
|
| 293 |
+
/* ๋ฐฐ๊ฒฝ ์ปฌ๋ฌ */
|
| 294 |
+
--background-color: #1a1a1a;
|
| 295 |
+
--card-bg: #2d2d2d;
|
| 296 |
+
--input-bg: #2d2d2d;
|
| 297 |
+
|
| 298 |
+
/* ํ
์คํธ ์ปฌ๋ฌ */
|
| 299 |
+
--text-color: #e5e5e5;
|
| 300 |
+
--text-secondary: #a1a1aa;
|
| 301 |
+
|
| 302 |
+
/* ๋ณด๋ ๋ฐ ๊ตฌ๋ถ์ */
|
| 303 |
+
--border-color: #404040;
|
| 304 |
+
--border-light: #525252;
|
| 305 |
+
|
| 306 |
+
/* ํ
์ด๋ธ ์ปฌ๋ฌ */
|
| 307 |
+
--table-even-bg: #333333;
|
| 308 |
+
--table-hover-bg: #404040;
|
| 309 |
+
|
| 310 |
+
/* ๊ทธ๋ฆผ์ */
|
| 311 |
+
--shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
|
| 312 |
+
--shadow-light: 0 2px 4px rgba(0, 0, 0, 0.2);
|
| 313 |
+
}
|
| 314 |
+
}
|
| 315 |
+
|
| 316 |
+
/* ============================================
|
| 317 |
+
3. ์๋ ๋คํฌ๋ชจ๋ ํด๋์ค (Gradio ํ ๊ธ์ฉ)
|
| 318 |
+
============================================ */
|
| 319 |
+
[data-theme="dark"],
|
| 320 |
+
.dark,
|
| 321 |
+
.gr-theme-dark {
|
| 322 |
+
/* ๋ฐฐ๊ฒฝ ์ปฌ๋ฌ */
|
| 323 |
+
--background-color: #1a1a1a;
|
| 324 |
+
--card-bg: #2d2d2d;
|
| 325 |
+
--input-bg: #2d2d2d;
|
| 326 |
+
|
| 327 |
+
/* ํ
์คํธ ์ปฌ๋ฌ */
|
| 328 |
+
--text-color: #e5e5e5;
|
| 329 |
+
--text-secondary: #a1a1aa;
|
| 330 |
+
|
| 331 |
+
/* ๋ณด๋ ๋ฐ ๊ตฌ๋ถ์ */
|
| 332 |
+
--border-color: #404040;
|
| 333 |
+
--border-light: #525252;
|
| 334 |
+
|
| 335 |
+
/* ํ
์ด๋ธ ์ปฌ๋ฌ */
|
| 336 |
+
--table-even-bg: #333333;
|
| 337 |
+
--table-hover-bg: #404040;
|
| 338 |
+
|
| 339 |
+
/* ๊ทธ๋ฆผ์ */
|
| 340 |
+
--shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
|
| 341 |
+
--shadow-light: 0 2px 4px rgba(0, 0, 0, 0.2);
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
/* ============================================
|
| 345 |
+
4. ๊ธฐ๋ณธ ์คํ์ผ (์๋ณธ UI ์ ์ง)
|
| 346 |
+
============================================ */
|
| 347 |
+
body {
|
| 348 |
+
font-family: 'Pretendard', 'Noto Sans KR', -apple-system, BlinkMacSystemFont, sans-serif;
|
| 349 |
+
background-color: var(--background-color) !important;
|
| 350 |
+
color: var(--text-color) !important;
|
| 351 |
+
line-height: 1.6;
|
| 352 |
+
margin: 0;
|
| 353 |
+
padding: 0;
|
| 354 |
+
transition: background-color 0.3s ease, color 0.3s ease;
|
| 355 |
+
}
|
| 356 |
+
|
| 357 |
+
/* ํธํฐ ์จ๊น ์ค์ */
|
| 358 |
+
footer {
|
| 359 |
+
visibility: hidden;
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
/* ============================================
|
| 363 |
+
5. Gradio ์ปจํ
์ด๋ ๊ฐ์ ์ ์ฉ
|
| 364 |
+
============================================ */
|
| 365 |
+
.gradio-container,
|
| 366 |
+
.gradio-container *,
|
| 367 |
+
.gr-app,
|
| 368 |
+
.gr-app *,
|
| 369 |
+
.gr-interface {
|
| 370 |
+
background-color: var(--background-color) !important;
|
| 371 |
+
color: var(--text-color) !important;
|
| 372 |
+
}
|
| 373 |
+
|
| 374 |
+
.gradio-container {
|
| 375 |
+
width: 100%;
|
| 376 |
+
margin: 0 auto;
|
| 377 |
+
padding: 20px;
|
| 378 |
+
background-color: var(--background-color) !important;
|
| 379 |
+
}
|
| 380 |
+
|
| 381 |
+
/* ============================================
|
| 382 |
+
6. ํค๋ ์คํ์ผ (์๋ณธ ์ ์ง)
|
| 383 |
+
============================================ */
|
| 384 |
+
.custom-header {
|
| 385 |
+
background: #FF7F00;
|
| 386 |
+
padding: 2rem;
|
| 387 |
+
border-radius: 15px;
|
| 388 |
+
margin-bottom: 20px;
|
| 389 |
+
box-shadow: var(--shadow);
|
| 390 |
+
text-align: center;
|
| 391 |
+
}
|
| 392 |
+
|
| 393 |
+
.custom-header h1 {
|
| 394 |
+
margin: 0;
|
| 395 |
+
font-size: 2.5rem;
|
| 396 |
+
font-weight: 700;
|
| 397 |
+
color: black;
|
| 398 |
+
}
|
| 399 |
+
|
| 400 |
+
.custom-header p {
|
| 401 |
+
margin: 10px 0 0;
|
| 402 |
+
font-size: 1.2rem;
|
| 403 |
+
color: black;
|
| 404 |
+
}
|
| 405 |
+
|
| 406 |
+
/* ============================================
|
| 407 |
+
7. ์นด๋ ๋ฐ ํจ๋ ์คํ์ผ (๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 408 |
+
============================================ */
|
| 409 |
+
.custom-frame,
|
| 410 |
+
.gr-form,
|
| 411 |
+
.gr-box,
|
| 412 |
+
.gr-panel,
|
| 413 |
+
[class*="frame"],
|
| 414 |
+
[class*="card"],
|
| 415 |
+
[class*="panel"] {
|
| 416 |
+
background-color: var(--card-bg) !important;
|
| 417 |
+
border: 1px solid var(--border-color) !important;
|
| 418 |
+
border-radius: var(--border-radius);
|
| 419 |
+
padding: 20px;
|
| 420 |
+
margin: 10px 0;
|
| 421 |
+
box-shadow: var(--shadow) !important;
|
| 422 |
+
color: var(--text-color) !important;
|
| 423 |
+
}
|
| 424 |
+
|
| 425 |
+
.custom-section-group {
|
| 426 |
+
margin-top: 20px;
|
| 427 |
+
padding: 0;
|
| 428 |
+
border: none;
|
| 429 |
+
border-radius: 0;
|
| 430 |
+
background-color: var(--background-color) !important;
|
| 431 |
+
box-shadow: none !important;
|
| 432 |
+
}
|
| 433 |
+
|
| 434 |
+
/* ============================================
|
| 435 |
+
8. ์
๋ ฅ ํ๋ ์คํ์ผ (๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 436 |
+
============================================ */
|
| 437 |
+
input[type="text"],
|
| 438 |
+
input[type="number"],
|
| 439 |
+
input[type="email"],
|
| 440 |
+
input[type="password"],
|
| 441 |
+
textarea,
|
| 442 |
+
select,
|
| 443 |
+
.gr-input,
|
| 444 |
+
.gr-text-input,
|
| 445 |
+
.gr-textarea,
|
| 446 |
+
.gr-dropdown,
|
| 447 |
+
.gr-sample-inputs {
|
| 448 |
+
background-color: var(--input-bg) !important;
|
| 449 |
+
color: var(--text-color) !important;
|
| 450 |
+
border: 1px solid var(--border-color) !important;
|
| 451 |
+
border-radius: var(--border-radius) !important;
|
| 452 |
+
padding: 12px !important;
|
| 453 |
+
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05) !important;
|
| 454 |
+
transition: all 0.3s ease !important;
|
| 455 |
+
}
|
| 456 |
+
|
| 457 |
+
input[type="text"]:focus,
|
| 458 |
+
input[type="number"]:focus,
|
| 459 |
+
input[type="email"]:focus,
|
| 460 |
+
input[type="password"]:focus,
|
| 461 |
+
textarea:focus,
|
| 462 |
+
select:focus,
|
| 463 |
+
.gr-input:focus,
|
| 464 |
+
.gr-text-input:focus,
|
| 465 |
+
.gr-textarea:focus,
|
| 466 |
+
.gr-dropdown:focus {
|
| 467 |
+
border-color: var(--primary-color) !important;
|
| 468 |
+
outline: none !important;
|
| 469 |
+
box-shadow: 0 0 0 2px rgba(251, 127, 13, 0.2) !important;
|
| 470 |
+
}
|
| 471 |
+
|
| 472 |
+
/* ============================================
|
| 473 |
+
9. ๋ฒํผ ์คํ์ผ (์๋ณธ ์ ์ง)
|
| 474 |
+
============================================ */
|
| 475 |
+
.custom-button {
|
| 476 |
+
border-radius: 30px !important;
|
| 477 |
+
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)) !important;
|
| 478 |
+
color: white !important;
|
| 479 |
+
font-size: 18px !important;
|
| 480 |
+
padding: 10px 20px !important;
|
| 481 |
+
border: none;
|
| 482 |
+
box-shadow: 0 4px 8px rgba(251, 127, 13, 0.25);
|
| 483 |
+
transition: transform 0.3s ease;
|
| 484 |
+
}
|
| 485 |
+
|
| 486 |
+
.custom-button:hover {
|
| 487 |
+
transform: translateY(-2px);
|
| 488 |
+
box-shadow: 0 6px 12px rgba(251, 127, 13, 0.3);
|
| 489 |
+
}
|
| 490 |
+
|
| 491 |
+
/* ์ผ๋ฐ ๋ฒํผ ๋คํฌ๋ชจ๋ ์ ์ฉ */
|
| 492 |
+
button:not([class*="custom"]):not([class*="primary"]):not([class*="secondary"]) {
|
| 493 |
+
background-color: var(--card-bg) !important;
|
| 494 |
+
color: var(--text-color) !important;
|
| 495 |
+
border-color: var(--border-color) !important;
|
| 496 |
+
}
|
| 497 |
+
|
| 498 |
+
/* ============================================
|
| 499 |
+
10. ํ
์คํธ ๋ฐ ๋ผ๋ฒจ ์คํ์ผ (๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 500 |
+
============================================ */
|
| 501 |
+
label,
|
| 502 |
+
.gr-label,
|
| 503 |
+
.gr-checkbox label,
|
| 504 |
+
.gr-radio label,
|
| 505 |
+
p, span, div {
|
| 506 |
+
color: var(--text-color) !important;
|
| 507 |
+
}
|
| 508 |
+
|
| 509 |
+
.custom-title {
|
| 510 |
+
font-size: 28px;
|
| 511 |
+
font-weight: bold;
|
| 512 |
+
margin-bottom: 10px;
|
| 513 |
+
color: var(--text-color) !important;
|
| 514 |
+
border-bottom: 2px solid var(--primary-color);
|
| 515 |
+
padding-bottom: 5px;
|
| 516 |
+
}
|
| 517 |
+
|
| 518 |
+
/* ============================================
|
| 519 |
+
11. ์น์
์ ๋ชฉ ์คํ์ผ (๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 520 |
+
============================================ */
|
| 521 |
+
.section-title {
|
| 522 |
+
display: flex;
|
| 523 |
+
align-items: center;
|
| 524 |
+
font-size: 20px;
|
| 525 |
+
font-weight: 700;
|
| 526 |
+
color: var(--text-color) !important;
|
| 527 |
+
margin-bottom: 10px;
|
| 528 |
+
padding-bottom: 5px;
|
| 529 |
+
border-bottom: 2px solid #FB7F0D;
|
| 530 |
+
font-family: 'Pretendard', 'Noto Sans KR', -apple-system, BlinkMacSystemFont, sans-serif;
|
| 531 |
+
}
|
| 532 |
+
|
| 533 |
+
.section-title img {
|
| 534 |
+
margin-right: 10px;
|
| 535 |
+
width: 24px;
|
| 536 |
+
height: 24px;
|
| 537 |
+
}
|
| 538 |
+
|
| 539 |
+
/* ============================================
|
| 540 |
+
12. ์ด๋ฏธ์ง ์ปจํ
์ด๋ ์คํ์ผ (๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 541 |
+
============================================ */
|
| 542 |
+
.image-container {
|
| 543 |
+
border-radius: var(--border-radius);
|
| 544 |
+
overflow: hidden;
|
| 545 |
+
border: 1px solid var(--border-color) !important;
|
| 546 |
+
transition: all 0.3s ease;
|
| 547 |
+
background-color: var(--card-bg) !important;
|
| 548 |
+
aspect-ratio: 1 / 1;
|
| 549 |
+
}
|
| 550 |
+
|
| 551 |
+
.image-container:hover {
|
| 552 |
+
box-shadow: var(--shadow-light);
|
| 553 |
+
}
|
| 554 |
+
|
| 555 |
+
.image-container img {
|
| 556 |
+
width: 100%;
|
| 557 |
+
height: 100%;
|
| 558 |
+
object-fit: contain;
|
| 559 |
+
}
|
| 560 |
+
|
| 561 |
+
/* ============================================
|
| 562 |
+
13. ํ
์ด๋ธ ์คํ์ผ (๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 563 |
+
============================================ */
|
| 564 |
+
table {
|
| 565 |
+
background-color: var(--card-bg) !important;
|
| 566 |
+
color: var(--text-color) !important;
|
| 567 |
+
border-color: var(--border-color) !important;
|
| 568 |
+
}
|
| 569 |
+
|
| 570 |
+
table th {
|
| 571 |
+
background-color: var(--primary-color) !important;
|
| 572 |
+
color: white !important;
|
| 573 |
+
border-color: var(--border-color) !important;
|
| 574 |
+
}
|
| 575 |
+
|
| 576 |
+
table td {
|
| 577 |
+
background-color: var(--card-bg) !important;
|
| 578 |
+
color: var(--text-color) !important;
|
| 579 |
+
border-color: var(--border-color) !important;
|
| 580 |
+
}
|
| 581 |
+
|
| 582 |
+
table tbody tr:nth-child(even) {
|
| 583 |
+
background-color: var(--table-even-bg) !important;
|
| 584 |
+
}
|
| 585 |
+
|
| 586 |
+
table tbody tr:hover {
|
| 587 |
+
background-color: var(--table-hover-bg) !important;
|
| 588 |
+
}
|
| 589 |
+
|
| 590 |
+
/* ============================================
|
| 591 |
+
14. ์ฒดํฌ๋ฐ์ค ๋ฐ ๋ผ๋์ค ๋ฒํผ (๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 592 |
+
============================================ */
|
| 593 |
+
input[type="checkbox"],
|
| 594 |
+
input[type="radio"] {
|
| 595 |
+
accent-color: var(--primary-color) !important;
|
| 596 |
+
}
|
| 597 |
+
|
| 598 |
+
/* ============================================
|
| 599 |
+
15. ์คํฌ๋กค๋ฐ ์คํ์ผ (๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 600 |
+
============================================ */
|
| 601 |
+
::-webkit-scrollbar {
|
| 602 |
+
width: 8px;
|
| 603 |
+
height: 8px;
|
| 604 |
+
}
|
| 605 |
+
|
| 606 |
+
::-webkit-scrollbar-track {
|
| 607 |
+
background: var(--card-bg);
|
| 608 |
+
border-radius: 10px;
|
| 609 |
+
}
|
| 610 |
+
|
| 611 |
+
::-webkit-scrollbar-thumb {
|
| 612 |
+
background: var(--primary-color);
|
| 613 |
+
border-radius: 10px;
|
| 614 |
+
}
|
| 615 |
+
|
| 616 |
+
::-webkit-scrollbar-thumb:hover {
|
| 617 |
+
background: var(--secondary-color);
|
| 618 |
+
}
|
| 619 |
+
|
| 620 |
+
/* ============================================
|
| 621 |
+
16. ์ถ๊ฐ Gradio ์ปดํฌ๋ํธ๋ค (๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 622 |
+
============================================ */
|
| 623 |
+
.gr-block,
|
| 624 |
+
.gr-group,
|
| 625 |
+
.gr-row,
|
| 626 |
+
.gr-column {
|
| 627 |
+
background-color: var(--background-color) !important;
|
| 628 |
+
color: var(--text-color) !important;
|
| 629 |
+
}
|
| 630 |
+
|
| 631 |
+
/* ============================================
|
| 632 |
+
17. ์ฝ๋ ๋ธ๋ก ๋ฐ pre ํ๊ทธ (๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 633 |
+
============================================ */
|
| 634 |
+
code,
|
| 635 |
+
pre,
|
| 636 |
+
.code-block {
|
| 637 |
+
background-color: var(--table-even-bg) !important;
|
| 638 |
+
color: var(--text-color) !important;
|
| 639 |
+
border-color: var(--border-color) !important;
|
| 640 |
+
}
|
| 641 |
+
|
| 642 |
+
/* ============================================
|
| 643 |
+
18. ์ ๋๋ฉ์ด์
์คํ์ผ (์๋ณธ ์ ์ง)
|
| 644 |
+
============================================ */
|
| 645 |
+
@keyframes fadeIn {
|
| 646 |
+
from { opacity: 0; transform: translateY(10px); }
|
| 647 |
+
to { opacity: 1; transform: translateY(0); }
|
| 648 |
+
}
|
| 649 |
+
|
| 650 |
+
.fade-in {
|
| 651 |
+
animation: fadeIn 0.5s ease-out;
|
| 652 |
+
}
|
| 653 |
+
|
| 654 |
+
/* ============================================
|
| 655 |
+
19. ์ ํ ์ ๋๋ฉ์ด์
(๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 656 |
+
============================================ */
|
| 657 |
+
* {
|
| 658 |
+
transition: background-color 0.3s ease,
|
| 659 |
+
color 0.3s ease,
|
| 660 |
+
border-color 0.3s ease !important;
|
| 661 |
+
}
|
| 662 |
+
|
| 663 |
+
/* ============================================
|
| 664 |
+
20. ๊ทธ๋ฃน ๋ํผ ๋ฐฐ๊ฒฝ ์์ ์ ๊ฑฐ
|
| 665 |
+
============================================ */
|
| 666 |
+
.custom-section-group,
|
| 667 |
+
.gr-block.gr-group {
|
| 668 |
+
background-color: var(--background-color) !important;
|
| 669 |
+
box-shadow: none !important;
|
| 670 |
+
}
|
| 671 |
+
|
| 672 |
+
.custom-section-group::before,
|
| 673 |
+
.custom-section-group::after,
|
| 674 |
+
.gr-block.gr-group::before,
|
| 675 |
+
.gr-block.gr-group::after {
|
| 676 |
+
display: none !important;
|
| 677 |
+
content: none !important;
|
| 678 |
+
}
|
| 679 |
+
|
| 680 |
+
/* ============================================
|
| 681 |
+
21. ์๋ฆผ ๋ฐ ๋ฉ์์ง (๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 682 |
+
============================================ */
|
| 683 |
+
.alert,
|
| 684 |
+
.message,
|
| 685 |
+
.notification,
|
| 686 |
+
[class*="alert"],
|
| 687 |
+
[class*="message"],
|
| 688 |
+
[class*="notification"] {
|
| 689 |
+
background-color: var(--card-bg) !important;
|
| 690 |
+
color: var(--text-color) !important;
|
| 691 |
+
border-color: var(--border-color) !important;
|
| 692 |
+
}
|
| 693 |
+
|
| 694 |
+
/* ============================================
|
| 695 |
+
22. ํดํ ๋ฐ ํ์
(๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 696 |
+
============================================ */
|
| 697 |
+
[data-tooltip]:hover::after,
|
| 698 |
+
.tooltip,
|
| 699 |
+
.popup {
|
| 700 |
+
background-color: var(--card-bg) !important;
|
| 701 |
+
color: var(--text-color) !important;
|
| 702 |
+
border-color: var(--border-color) !important;
|
| 703 |
+
box-shadow: var(--shadow-light) !important;
|
| 704 |
+
}
|
| 705 |
+
|
| 706 |
+
/* ============================================
|
| 707 |
+
23. ๋ชจ๋ฌ ๋ฐ ์ค๋ฒ๋ ์ด (๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 708 |
+
============================================ */
|
| 709 |
+
.modal,
|
| 710 |
+
.overlay,
|
| 711 |
+
[class*="modal"],
|
| 712 |
+
[class*="overlay"] {
|
| 713 |
+
background-color: var(--card-bg) !important;
|
| 714 |
+
color: var(--text-color) !important;
|
| 715 |
+
border-color: var(--border-color) !important;
|
| 716 |
+
}
|
| 717 |
+
|
| 718 |
+
/* ============================================
|
| 719 |
+
24. ์์ฝ๋์ธ ๋ฐ ๋๋กญ๋ค์ด (๋คํฌ๋ชจ๋ ์ ์ฉ)
|
| 720 |
+
============================================ */
|
| 721 |
+
details {
|
| 722 |
+
background-color: var(--card-bg) !important;
|
| 723 |
+
border-color: var(--border-color) !important;
|
| 724 |
+
color: var(--text-color) !important;
|
| 725 |
+
}
|
| 726 |
+
|
| 727 |
+
details summary {
|
| 728 |
+
background-color: var(--card-bg) !important;
|
| 729 |
+
color: var(--text-color) !important;
|
| 730 |
+
}
|
| 731 |
+
"""
|
| 732 |
+
|
| 733 |
+
# FontAwesome ์์ด์ฝ ํฌํจ
|
| 734 |
+
fontawesome_link = """
|
| 735 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
| 736 |
+
"""
|
| 737 |
+
|
| 738 |
+
# Gradio ์ธํฐํ์ด์ค ์์ฑ
|
| 739 |
+
transformer = ImageTransformer()
|
| 740 |
+
|
| 741 |
+
def process_images(images, mode):
|
| 742 |
+
if not images:
|
| 743 |
+
return None, None, None, "์ด๋ฏธ์ง๋ฅผ ์
๋ก๋ํด์ฃผ์ธ์."
|
| 744 |
+
|
| 745 |
+
results = []
|
| 746 |
+
all_selected_methods = []
|
| 747 |
+
all_similarities = []
|
| 748 |
+
method_details = [] # ๊ฐ ๋ณํ์ ์ค์ ์์น ์ ์ฅ
|
| 749 |
+
|
| 750 |
+
# ์์ ๋๋ ํ ๋ฆฌ ์์ฑ
|
| 751 |
+
with tempfile.TemporaryDirectory() as temp_dir:
|
| 752 |
+
for idx, image_data in enumerate(images):
|
| 753 |
+
# Gallery์์ ๋ฐ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
|
| 754 |
+
if isinstance(image_data, tuple):
|
| 755 |
+
# Gallery๊ฐ ํํ(ํ์ผ ๊ฒฝ๋ก, ํ์ผ ์ด๋ฆ) ํํ๋ก ๋ฐํํ๋ ๊ฒฝ์ฐ
|
| 756 |
+
if len(image_data) > 0:
|
| 757 |
+
image_path = image_data[0] if isinstance(image_data[0], str) else image_data[1]
|
| 758 |
+
image = Image.open(image_path)
|
| 759 |
+
original_filename = os.path.basename(image_path)
|
| 760 |
+
else:
|
| 761 |
+
continue
|
| 762 |
+
elif isinstance(image_data, str): # ํ์ผ ๊ฒฝ๋ก์ธ ๊ฒฝ์ฐ
|
| 763 |
+
image = Image.open(image_data)
|
| 764 |
+
original_filename = os.path.basename(image_data)
|
| 765 |
+
elif isinstance(image_data, dict) and 'name' in image_data: # ํ์ผ ์ ๋ณด ๋์
๋๋ฆฌ์ธ ๊ฒฝ์ฐ
|
| 766 |
+
image = Image.open(image_data['name'])
|
| 767 |
+
original_filename = os.path.basename(image_data['name'])
|
| 768 |
+
else: # PIL Image ๊ฐ์ฒด์ธ ๊ฒฝ์ฐ
|
| 769 |
+
image = image_data
|
| 770 |
+
original_filename = f"image_{idx+1}.jpg"
|
| 771 |
+
|
| 772 |
+
# RGB๋ก ๋ณํ (RGBA ๋ฑ ๋ค๋ฅธ ๋ชจ๋ ์ฒ๋ฆฌ)
|
| 773 |
+
if image.mode != 'RGB':
|
| 774 |
+
image = image.convert('RGB')
|
| 775 |
+
|
| 776 |
+
if mode == "๋๋ค ๋ณํ":
|
| 777 |
+
# 95% ๋ชฉํ - ๊ฐ๋ 5
|
| 778 |
+
selected_methods = random.sample(list(transformer.method_info.keys()), 5)
|
| 779 |
+
intensity = 0.5
|
| 780 |
+
target_similarity = 95
|
| 781 |
+
else: # ์ต๋ ๋ณํ
|
| 782 |
+
# 90% ๋ชฉํ - ๋ชจ๋ ๋ฐฉ๋ฒ ์ ์ฉ, ๊ฐ๋ 10
|
| 783 |
+
selected_methods = list(transformer.method_info.keys())
|
| 784 |
+
intensity = 1.0
|
| 785 |
+
target_similarity = 90
|
| 786 |
+
|
| 787 |
+
transformed, details = transformer.transform_image_with_details(image, selected_methods, intensity)
|
| 788 |
+
similarity = transformer.calculate_similarity(image, transformed)
|
| 789 |
+
|
| 790 |
+
results.append(transformed)
|
| 791 |
+
all_selected_methods.append(selected_methods)
|
| 792 |
+
all_similarities.append(similarity)
|
| 793 |
+
method_details.append(details)
|
| 794 |
+
|
| 795 |
+
# ๋ณํ๋ ์ด๋ฏธ์ง ์ ์ฅ - ๋ณ๊ฒฝ_์๋ํ์ผ๋ช
|
| 796 |
+
name_part, ext = os.path.splitext(original_filename)
|
| 797 |
+
new_filename = f"๋ณ๊ฒฝ_{name_part}{ext}"
|
| 798 |
+
transformed.save(os.path.join(temp_dir, new_filename), "JPEG", quality=95)
|
| 799 |
+
|
| 800 |
+
# ZIP ํ์ผ ์์ฑ - ์ด๋ฏธ์ง๋ณ๊ฒฝ_ํ๊ตญ๋ ์ง_์๊ฐ ํ์
|
| 801 |
+
kst = pytz.timezone('Asia/Seoul')
|
| 802 |
+
now_kst = datetime.datetime.now(kst)
|
| 803 |
+
zip_filename = f"์ด๋ฏธ์ง๋ณ๊ฒฝ_{now_kst.strftime('%y.%m.%d_%H.%M')}.zip"
|
| 804 |
+
zip_path = os.path.join(temp_dir, zip_filename)
|
| 805 |
+
|
| 806 |
+
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
| 807 |
+
for filename in os.listdir(temp_dir):
|
| 808 |
+
if filename.endswith(('.jpg', '.jpeg', '.png')):
|
| 809 |
+
zipf.write(os.path.join(temp_dir, filename), filename)
|
| 810 |
+
|
| 811 |
+
# ZIP ํ์ผ์ ์ค์ ๋ก ์ ์ฅ
|
| 812 |
+
zip_output_path = os.path.join(tempfile.gettempdir(), zip_filename)
|
| 813 |
+
shutil.copy2(zip_path, zip_output_path)
|
| 814 |
+
|
| 815 |
+
# ๋ณํ ์ค๋ช
์์ฑ
|
| 816 |
+
avg_similarity = sum(all_similarities) / len(all_similarities)
|
| 817 |
+
|
| 818 |
+
# ์ ์ฉ๋ ๋ฐฉ๋ฒ ์ค๋ช
์์ฑ - ๊ธฐ๋ณธ ์ค๋ช
๊ณผ ์์น๋ฅผ ํจ๊ป ํฌํจ
|
| 819 |
+
if method_details:
|
| 820 |
+
detail_text = "### ์ ์ฉ๋ ๋ณํ ๋ฐฉ๋ฒ\n\n"
|
| 821 |
+
for method, detail in method_details[0].items():
|
| 822 |
+
# ๊ธฐ๋ณธ ์ค๋ช
๊ณผ ์ค์ ์ ์ฉ ์์น๋ฅผ ๊ฒฐํฉ
|
| 823 |
+
base_description = transformer.method_info[method]['description']
|
| 824 |
+
detail_text += f"**{method}**\n{base_description}\n์ค์ ์ ์ฉ ์์น: {detail}\n\n"
|
| 825 |
+
|
| 826 |
+
detail_text += f"\n**๋ณํ ๊ฒฐ๊ณผ**\n"
|
| 827 |
+
detail_text += f"- ์ฒ๋ฆฌ๋ ์ด๋ฏธ์ง ์: {len(images)}๊ฐ\n"
|
| 828 |
+
detail_text += f"- ํ๊ท ์ ์ฌ๋: {avg_similarity:.2f}%\n"
|
| 829 |
+
detail_text += f"- ๋ชฉํ ์ ์ฌ๋: {target_similarity}%\n"
|
| 830 |
+
else:
|
| 831 |
+
detail_text = "๋ณํ ์ ๋ณด ์๏ฟฝ๏ฟฝ๏ฟฝ"
|
| 832 |
+
|
| 833 |
+
# ์ ํ๋ ๋ฐฉ๋ฒ๋ค (์ฒซ ๋ฒ์งธ ์ด๋ฏธ์ง ๊ธฐ์ค)
|
| 834 |
+
selected_methods_display = all_selected_methods[0]
|
| 835 |
+
|
| 836 |
+
return results, selected_methods_display, detail_text, zip_output_path
|
| 837 |
+
|
| 838 |
+
# Gradio ์ธํฐํ์ด์ค ๊ตฌ์ฑ
|
| 839 |
+
def create_app():
|
| 840 |
+
with gr.Blocks(css=custom_css, title="๋ค์ด๋ฒ ๋ธ๋ก๊ทธ ์ ์ฌ ์ด๋ฏธ์ง ํํผ ๋๊ตฌ", theme=gr.themes.Default(
|
| 841 |
+
primary_hue="orange",
|
| 842 |
+
secondary_hue="orange",
|
| 843 |
+
font=[gr.themes.GoogleFont("Noto Sans KR"), "ui-sans-serif", "system-ui"]
|
| 844 |
+
)) as demo:
|
| 845 |
+
gr.HTML(fontawesome_link)
|
| 846 |
+
|
| 847 |
+
# ์ด๋ฏธ์ง ๋ณํ ๊ธฐ๋ฅ ์น์
- ํญ ์์ด ์ง์ ๊ตฌํ
|
| 848 |
+
with gr.Row():
|
| 849 |
+
with gr.Column(scale=1):
|
| 850 |
+
# ์ด๋ฏธ์ง ์
๋ก๋ ์น์
|
| 851 |
+
with gr.Column(elem_classes="custom-frame"):
|
| 852 |
+
gr.HTML('<div class="section-title"><img src="https://cdn-icons-png.flaticon.com/512/3097/3097412.png"> ์ด๋ฏธ์ง ์
๋ก๋</div>')
|
| 853 |
+
input_images = gr.Gallery(
|
| 854 |
+
label="์๋ณธ ์ด๋ฏธ์ง",
|
| 855 |
+
columns=3,
|
| 856 |
+
height="400px",
|
| 857 |
+
allow_preview=True,
|
| 858 |
+
object_fit="contain",
|
| 859 |
+
type="filepath",
|
| 860 |
+
elem_id="input_gallery"
|
| 861 |
+
)
|
| 862 |
+
|
| 863 |
+
with gr.Column(scale=1):
|
| 864 |
+
# ๋ณํ๋ ์ด๋ฏธ์ง ์น์
|
| 865 |
+
with gr.Column(elem_classes="custom-frame"):
|
| 866 |
+
gr.HTML('<div class="section-title"><img src="https://cdn-icons-png.flaticon.com/512/1375/1375106.png"> ๋ณํ๋ ์ด๋ฏธ์ง</div>')
|
| 867 |
+
output_images = gr.Gallery(
|
| 868 |
+
label="",
|
| 869 |
+
columns=3,
|
| 870 |
+
height="400px",
|
| 871 |
+
allow_preview=True,
|
| 872 |
+
object_fit="contain",
|
| 873 |
+
show_download_button=True,
|
| 874 |
+
elem_id="output_gallery"
|
| 875 |
+
)
|
| 876 |
+
|
| 877 |
+
# ๋ณํ ์ต์
๋ฐ ๊ฒฐ๊ณผ ์น์
|
| 878 |
+
with gr.Row():
|
| 879 |
+
with gr.Column(scale=1):
|
| 880 |
+
with gr.Column(elem_classes="custom-frame"):
|
| 881 |
+
gr.HTML('<div class="section-title"><img src="https://cdn-icons-png.flaticon.com/512/1022/1022293.png"> ๋ณํ ์ต์
</div>')
|
| 882 |
+
with gr.Row():
|
| 883 |
+
random_btn = gr.Button("๐ฒ ๋๋ค ๋ณํ (95% ๋ชฉํ)", elem_classes="custom-button")
|
| 884 |
+
max_btn = gr.Button("โก ์ต๋ ๋ณํ (90% ๋ชฉํ)", elem_classes="custom-button")
|
| 885 |
+
|
| 886 |
+
with gr.Column(scale=1):
|
| 887 |
+
with gr.Column(elem_classes="custom-frame"):
|
| 888 |
+
gr.HTML('<div class="section-title"><img src="https://cdn-icons-png.flaticon.com/512/3153/3153376.png"> ๊ฒฐ๊ณผ ๋ค์ด๋ก๋</div>')
|
| 889 |
+
download_file = gr.File(label="ZIP ํ์ผ ๋ค์ด๋ก๋")
|
| 890 |
+
|
| 891 |
+
# ์ ์ฉ๋ ๋ณํ ๋ฐฉ๋ฒ ์ ๋ณด
|
| 892 |
+
with gr.Column(elem_classes="custom-frame"):
|
| 893 |
+
gr.HTML('<div class="section-title"><img src="https://cdn-icons-png.flaticon.com/512/4297/4297825.png"> ์ ์ฉ๋ ๋ณํ ์ ๋ณด</div>')
|
| 894 |
+
|
| 895 |
+
with gr.Row():
|
| 896 |
+
with gr.Column(scale=1):
|
| 897 |
+
method_checkboxes = gr.CheckboxGroup(
|
| 898 |
+
choices=list(transformer.method_info.keys()),
|
| 899 |
+
label="์ ์ฉ๋ ๋ณํ ๋ฐฉ๋ฒ",
|
| 900 |
+
interactive=False
|
| 901 |
+
)
|
| 902 |
+
|
| 903 |
+
with gr.Column(scale=1):
|
| 904 |
+
status_text = gr.Textbox(
|
| 905 |
+
label="๋ณํ ์์ธ ์ ๋ณด",
|
| 906 |
+
interactive=False,
|
| 907 |
+
lines=12
|
| 908 |
+
)
|
| 909 |
+
|
| 910 |
+
# ์ด๋ฒคํธ ํธ๋ค๋ฌ
|
| 911 |
+
def random_transform(images):
|
| 912 |
+
if not images:
|
| 913 |
+
return None, None, "์ด๋ฏธ์ง๋ฅผ ๋จผ์ ์
๋ก๋ํด์ฃผ์ธ์.", None
|
| 914 |
+
return process_images(images, "๋๋ค ๋ณํ")
|
| 915 |
+
|
| 916 |
+
def max_transform(images):
|
| 917 |
+
if not images:
|
| 918 |
+
return None, None, "์ด๋ฏธ์ง๋ฅผ ๋จผ์ ์
๋ก๋ํด์ฃผ์ธ์.", None
|
| 919 |
+
return process_images(images, "์ต๋ ๋ณํ")
|
| 920 |
+
|
| 921 |
+
random_btn.click(
|
| 922 |
+
fn=random_transform,
|
| 923 |
+
inputs=[input_images],
|
| 924 |
+
outputs=[output_images, method_checkboxes, status_text, download_file]
|
| 925 |
+
)
|
| 926 |
+
|
| 927 |
+
max_btn.click(
|
| 928 |
+
fn=max_transform,
|
| 929 |
+
inputs=[input_images],
|
| 930 |
+
outputs=[output_images, method_checkboxes, status_text, download_file]
|
| 931 |
+
)
|
| 932 |
+
|
| 933 |
+
return demo
|
| 934 |
+
|
| 935 |
+
if __name__ == "__main__":
|
| 936 |
+
app = create_app()
|
| 937 |
+
app.queue(max_size=10) # ์์ฒญ์ ์์ฐจ์ ์ผ๋ก ์ฒ๋ฆฌํ๋๋ก ํ ์ค์
|
| 938 |
+
app.launch(share=False, inbrowser=True, width="100%")
|