Kims12 commited on
Commit
9071926
ยท
verified ยท
1 Parent(s): 2f6470a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +249 -1
app.py CHANGED
@@ -13,6 +13,8 @@ from transformers import pipeline # ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ import
13
 
14
  load_dotenv()
15
 
 
 
16
  # ๊ธฐ์กด ์ฝ”๋“œ ์œ ์ง€ (๋กœ๊น…, ํ•จ์ˆ˜ ๋“ฑ ๋ชจ๋“  ๊ธฐ๋Šฅ ์ฝ”๋“œ)
17
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
18
  logger = logging.getLogger(__name__)
@@ -42,6 +44,140 @@ def save_binary_file(file_name, data):
42
  with open(file_name, "wb") as f:
43
  f.write(data)
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  def translate_prompt_to_english(prompt):
46
  # ๊ธฐ์กด ํ•จ์ˆ˜ ์œ ์ง€
47
  if not re.search("[๊ฐ€-ํžฃ]", prompt):
@@ -906,7 +1042,39 @@ with gr.Blocks(css=custom_css) as demo:
906
  </p>
907
  </div>
908
  </div>
909
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
910
 
911
  with gr.TabItem("โœจ ์ด์ปค๋จธ์Šค ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ", elem_classes="tab-content"):
912
  with gr.Row(equal_height=True):
@@ -1027,6 +1195,86 @@ with gr.Blocks(css=custom_css) as demo:
1027
  with gr.Row():
1028
  bg_remove_status = gr.Textbox(label="์ƒํƒœ", lines=2, elem_classes="custom-input")
1029
  bg_remove_btn = gr.Button('โœ‚๏ธ ๋ฐฐ๊ฒฝ ์ œ๊ฑฐํ•˜๊ธฐ', elem_classes="custom-button primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1030
 
1031
  # ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
1032
  image_change_btn1.click(
 
13
 
14
  load_dotenv()
15
 
16
+
17
+
18
  # ๊ธฐ์กด ์ฝ”๋“œ ์œ ์ง€ (๋กœ๊น…, ํ•จ์ˆ˜ ๋“ฑ ๋ชจ๋“  ๊ธฐ๋Šฅ ์ฝ”๋“œ)
19
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
20
  logger = logging.getLogger(__name__)
 
44
  with open(file_name, "wb") as f:
45
  f.write(data)
46
 
47
+
48
+ # ์ด๋ฏธ์ง€ ํ•„ํ„ฐ ๊ธฐ๋Šฅ์„ ์œ„ํ•œ ์ถ”๊ฐ€ ์ฝ”๋“œ
49
+ import cv2
50
+ import numpy as np
51
+ from PIL import Image, ImageEnhance, ImageFilter
52
+ import tempfile
53
+ from datetime import datetime, timedelta
54
+
55
+ # ์ด๋ฏธ์ง€ ํ•„ํ„ฐ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜
56
+ def adjust_brightness(image, value):
57
+ """์ด๋ฏธ์ง€ ๋ฐ๊ธฐ ์กฐ์ ˆ"""
58
+ value = float(value - 1) * 100 # 0-2 ๋ฒ”์œ„๋ฅผ -100์—์„œ +100์œผ๋กœ ๋ณ€ํ™˜
59
+ hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
60
+ h, s, v = cv2.split(hsv)
61
+ v = cv2.add(v, value)
62
+ v = np.clip(v, 0, 255)
63
+ final_hsv = cv2.merge((h, s, v))
64
+ return cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
65
+
66
+ def adjust_contrast(image, value):
67
+ """์ด๋ฏธ์ง€ ๋Œ€๋น„ ์กฐ์ ˆ"""
68
+ value = float(value)
69
+ return np.clip(image * value, 0, 255).astype(np.uint8)
70
+
71
+ def adjust_saturation(image, value):
72
+ """์ด๋ฏธ์ง€ ์ฑ„๋„ ์กฐ์ ˆ"""
73
+ value = float(value - 1) * 100 # 0-2 ๋ฒ”์œ„๋ฅผ -100์—์„œ +100์œผ๋กœ ๋ณ€ํ™˜
74
+ hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
75
+ h, s, v = cv2.split(hsv)
76
+ s = cv2.add(s, value)
77
+ s = np.clip(s, 0, 255)
78
+ final_hsv = cv2.merge((h, s, v))
79
+ return cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
80
+
81
+ def adjust_temperature(image, value):
82
+ """์ด๋ฏธ์ง€ ์ƒ‰์˜จ๋„ ์กฐ์ ˆ (์ƒ‰์ƒ ๋ฐธ๋Ÿฐ์Šค)"""
83
+ value = float(value) * 30 # ํšจ๊ณผ ์Šค์ผ€์ผ ์กฐ์ ˆ
84
+ b, g, r = cv2.split(image)
85
+ if value > 0: # ๋”ฐ๋œปํ•˜๊ฒŒ
86
+ r = cv2.add(r, value)
87
+ b = cv2.subtract(b, value)
88
+ else: # ์ฐจ๊ฐ‘๊ฒŒ
89
+ r = cv2.add(r, value)
90
+ b = cv2.subtract(b, value)
91
+
92
+ r = np.clip(r, 0, 255)
93
+ b = np.clip(b, 0, 255)
94
+ return cv2.merge([b, g, r])
95
+
96
+ def adjust_tint(image, value):
97
+ """์ด๋ฏธ์ง€ ์ƒ‰์กฐ ์กฐ์ ˆ"""
98
+ hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
99
+ h, s, v = cv2.split(hsv_image)
100
+ h = cv2.add(h, int(value))
101
+ h = np.clip(h, 0, 179) # Hue ๊ฐ’์€ 0-179 ๋ฒ”์œ„
102
+ final_hsv = cv2.merge((h, s, v))
103
+ return cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
104
+
105
+ def adjust_exposure(image, value):
106
+ """์ด๋ฏธ์ง€ ๋…ธ์ถœ ์กฐ์ ˆ"""
107
+ enhancer = ImageEnhance.Brightness(Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)))
108
+ img_enhanced = enhancer.enhance(1 + float(value) / 5.0)
109
+ return cv2.cvtColor(np.array(img_enhanced), cv2.COLOR_RGB2BGR)
110
+
111
+ def adjust_vibrance(image, value):
112
+ """์ด๋ฏธ์ง€ ํ™œ๊ธฐ ์กฐ์ ˆ"""
113
+ img = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
114
+ converter = ImageEnhance.Color(img)
115
+ factor = 1 + (float(value) / 100.0)
116
+ img = converter.enhance(factor)
117
+ return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
118
+
119
+ def adjust_color_mixer_blues(image, value):
120
+ """์ด๋ฏธ์ง€ ์ปฌ๋Ÿฌ ๋ฏน์„œ (๋ธ”๋ฃจ) ์กฐ์ ˆ"""
121
+ b, g, r = cv2.split(image)
122
+ b = cv2.add(b, float(value))
123
+ b = np.clip(b, 0, 255)
124
+ return cv2.merge([b, g, r])
125
+
126
+ def adjust_shadows(image, value):
127
+ """์ด๋ฏธ์ง€ ๊ทธ๋ฆผ์ž ์กฐ์ ˆ"""
128
+ pil_image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
129
+ enhancer = ImageEnhance.Brightness(pil_image)
130
+ factor = 1 + (float(value) / 100.0)
131
+ pil_image = enhancer.enhance(factor)
132
+ return cv2.cvtColor(np.array(pil_image), cv2.COLOR_BGR2RGB)
133
+
134
+ def process_image(image, brightness, contrast, saturation, temperature, tint, exposure, vibrance, color_mixer_blues, shadows):
135
+ """๋ชจ๋“  ์กฐ์ • ์‚ฌํ•ญ์„ ์ด๋ฏธ์ง€์— ์ ์šฉ"""
136
+ if image is None:
137
+ return None
138
+
139
+ # PIL ์ด๋ฏธ์ง€๋ฅผ OpenCV ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜
140
+ image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
141
+
142
+ # ์กฐ์ • ์‚ฌํ•ญ ์ˆœ์ฐจ ์ ์šฉ
143
+ image = adjust_brightness(image, brightness)
144
+ image = adjust_contrast(image, contrast)
145
+ image = adjust_saturation(image, saturation)
146
+ image = adjust_temperature(image, temperature)
147
+ image = adjust_tint(image, tint)
148
+ image = adjust_exposure(image, exposure)
149
+ image = adjust_vibrance(image, vibrance)
150
+ image = adjust_color_mixer_blues(image, color_mixer_blues)
151
+ image = adjust_shadows(image, shadows)
152
+
153
+ # PIL ์ด๋ฏธ์ง€๋กœ ๋‹ค์‹œ ๋ณ€ํ™˜
154
+ return Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
155
+
156
+ def download_image(image, input_image_name):
157
+ """์ด๋ฏธ์ง€๋ฅผ JPG ํ˜•์‹์œผ๋กœ ์ €์žฅํ•˜๊ณ  ๊ฒฝ๋กœ ๋ฐ˜ํ™˜"""
158
+ if image is None:
159
+ return None
160
+
161
+ # ํ•œ๊ตญ ์‹œ๊ฐ„ ํƒ€์ž„์Šคํƒฌํ”„ ์ƒ์„ฑ
162
+ def get_korean_timestamp():
163
+ korea_time = datetime.utcnow() + timedelta(hours=9)
164
+ return korea_time.strftime('%Y%m%d_%H%M%S')
165
+
166
+ timestamp = get_korean_timestamp()
167
+ if input_image_name and hasattr(input_image_name, 'name'):
168
+ base_name = input_image_name.name.split('.')[0] # ํŒŒ์ผ ๊ฐ์ฒด์—์„œ ์ด๋ฆ„ ์ถ”์ถœ
169
+ else:
170
+ base_name = "์ด๋ฏธ์ง€"
171
+
172
+ file_name = f"[๋์žฅAI]๋์žฅํ•„ํ„ฐ_{base_name}_{timestamp}.jpg"
173
+
174
+ # ํŒŒ์ผ ์ €์žฅ
175
+ temp_file_path = tempfile.gettempdir() + "/" + file_name
176
+ image.save(temp_file_path, format="JPEG")
177
+ return temp_file_path
178
+
179
+
180
+
181
  def translate_prompt_to_english(prompt):
182
  # ๊ธฐ์กด ํ•จ์ˆ˜ ์œ ์ง€
183
  if not re.search("[๊ฐ€-ํžฃ]", prompt):
 
1042
  </p>
1043
  </div>
1044
  </div>
1045
+
1046
+ # ์‚ฌ์šฉ ์„ค๋ช…์„œ ํƒญ์˜ HTML์— ์ด๋ฏธ์ง€ ํ•„ํ„ฐ ๊ธฐ๋Šฅ ์„ค๋ช… ์ถ”๊ฐ€
1047
+ # ๊ธฐ์กด <div class="manual-section"> ํŒจํ„ด๊ณผ ๋™์ผํ•˜๊ฒŒ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค
1048
+
1049
+ # ์ด ๋ถ€๋ถ„์„ ์‚ฌ์šฉ ์„ค๋ช…์„œ HTML์˜ ์ ์ ˆํ•œ ์œ„์น˜ (๋‹ค๋ฅธ ์„น์…˜ ๋‹ค์Œ)์— ์ถ”๊ฐ€
1050
+ """
1051
+ <div class="manual-section">
1052
+ <div class="manual-section-title"><i class="fas fa-sliders-h"></i> ์ด๋ฏธ์ง€ ํ•„ํ„ฐ ๊ธฐ๋Šฅ</div>
1053
+ <p class="manual-text">
1054
+ <span style="font-size: 1.1rem; font-weight: 600; color: #5561e9;">์ด๋ฏธ์ง€ ํŽธ์ง‘ ๋„๊ตฌ</span><br>
1055
+ ์ด๋ฏธ์ง€ ํ•„ํ„ฐ ํƒญ์—์„œ๋Š” ๋‹ค์–‘ํ•œ ์Šฌ๋ผ์ด๋”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€๋ฅผ ์‰ฝ๊ฒŒ ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.<br>
1056
+ ์ฃผ์š” ๊ธฐ๋Šฅ:
1057
+ <ul>
1058
+ <li>๋ฐ๊ธฐ, ๋Œ€๋น„, ์ฑ„๋„, ์ƒ‰์˜จ๋„ ๋“ฑ ๋‹ค์–‘ํ•œ ์กฐ์ ˆ ์˜ต์…˜</li>
1059
+ <li>๋ชจ๋“  ๋ณ€๊ฒฝ์‚ฌํ•ญ ์‹ค์‹œ๊ฐ„ ๋ฏธ๋ฆฌ๋ณด๊ธฐ</li>
1060
+ <li>ํŽธ์ง‘ ์™„๋ฃŒ ํ›„ JPG ํ˜•์‹์œผ๋กœ ์ €์žฅ ๊ฐ€๋Šฅ</li>
1061
+ </ul>
1062
+
1063
+ <div class="tip-box">
1064
+ <i class="fas fa-lightbulb"></i> <strong>ํŒ:</strong> ๊ฐ ์Šฌ๋ผ์ด๋”๋ฅผ ์กฐ๊ธˆ์”ฉ ์กฐ์ ˆํ•˜๋ฉฐ ์›ํ•˜๋Š” ํšจ๊ณผ๋ฅผ ์ฐพ์•„๋ณด์„ธ์š”.
1065
+ </div>
1066
+ </p>
1067
+ </div>
1068
+ """
1069
+
1070
+ # ๋˜ํ•œ "์ฃผ์š” ๊ธฐ๋Šฅ" ์„น์…˜์˜ ๊ทธ๋ฆฌ๋“œ์— ์ด๋ฏธ์ง€ ํ•„ํ„ฐ ํ•ญ๋ชฉ ์ถ”๊ฐ€
1071
+ # ๊ธฐ์กด ๊ทธ๋ฆฌ๋“œ ํ•ญ๋ชฉ๋“ค ๋‹ค์Œ์— ์ด ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”
1072
+ """
1073
+ <div>
1074
+ <p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-sliders-h"></i> ์ด๋ฏธ์ง€ ํ•„ํ„ฐ</p>
1075
+ ๋ฐ๊ธฐ, ๋Œ€๋น„, ์ฑ„๋„ ๋“ฑ์„ ์กฐ์ ˆํ•˜์—ฌ ์ด๋ฏธ์ง€๋ฅผ ์ „๋ฌธ์ ์œผ๋กœ ํŽธ์ง‘ํ•ฉ๋‹ˆ๋‹ค.
1076
+ </div>
1077
+ """)
1078
 
1079
  with gr.TabItem("โœจ ์ด์ปค๋จธ์Šค ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ", elem_classes="tab-content"):
1080
  with gr.Row(equal_height=True):
 
1195
  with gr.Row():
1196
  bg_remove_status = gr.Textbox(label="์ƒํƒœ", lines=2, elem_classes="custom-input")
1197
  bg_remove_btn = gr.Button('โœ‚๏ธ ๋ฐฐ๊ฒฝ ์ œ๊ฑฐํ•˜๊ธฐ', elem_classes="custom-button primary")
1198
+
1199
+
1200
+ # UI ๊ตฌ์„ฑ์— ์ด๋ฏธ์ง€ ํ•„ํ„ฐ ํƒญ ์ถ”๊ฐ€ (๊ธฐ์กด ํƒญ ๋‹ค์Œ์— ์ถ”๊ฐ€)
1201
+ with gr.TabItem("๐Ÿ–Œ๏ธ ์ด๋ฏธ์ง€ ํ•„ํ„ฐ", elem_classes="tab-content"):
1202
+ with gr.Row(equal_height=True):
1203
+ # ์™ผ์ชฝ ์—ด: ๋น„์œจ 3
1204
+ with gr.Column(scale=3, elem_classes="panel"):
1205
+ gr.HTML('<div class="section-title"><i class="fas fa-sliders-h"></i> ์ด๋ฏธ์ง€ ํ•„ํ„ฐ ์„ค์ •</div>')
1206
+ # ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ
1207
+ filter_input_image = gr.Image(type="pil", label="์ด๋ฏธ์ง€ ์—…๋กœ๋“œ", elem_classes="image-container")
1208
+
1209
+ # ์กฐ์ • ์Šฌ๋ผ์ด๋”
1210
+ with gr.Group():
1211
+ brightness_slider = gr.Slider(0.0, 2.0, value=1.0, step=0.1, label="๋ฐ๊ธฐ ์กฐ์ ˆ")
1212
+ contrast_slider = gr.Slider(0.5, 1.5, value=1.0, step=0.1, label="๋Œ€๋น„ ์กฐ์ ˆ")
1213
+ saturation_slider = gr.Slider(0.0, 2.0, value=1.0, step=0.1, label="์ฑ„๋„ ์กฐ์ ˆ")
1214
+ temperature_slider = gr.Slider(-1.0, 1.0, value=0.0, step=0.1, label="์ƒ‰์˜จ๋„ ์กฐ์ ˆ")
1215
+ tint_slider = gr.Slider(-100, 100, value=0, step=1, label="์ƒ‰์กฐ ์กฐ์ ˆ")
1216
+ exposure_slider = gr.Slider(-5.0, 5.0, value=0.0, step=0.1, label="๋…ธ์ถœ ์กฐ์ ˆ")
1217
+ vibrance_slider = gr.Slider(-100.0, 100.0, value=0.0, step=1.0, label="ํ™œ๊ธฐ ์กฐ์ ˆ")
1218
+ color_mixer_blues_slider = gr.Slider(-100.0, 100.0, value=0.0, step=1.0, label="์ปฌ๋Ÿฌ ๋ฏน์„œ (๋ธ”๋ฃจ)")
1219
+ shadows_slider = gr.Slider(-100.0, 100.0, value=0.0, step=1.0, label="๊ทธ๋ฆผ์ž ์กฐ์ ˆ")
1220
+
1221
+ # ์˜ค๋ฅธ์ชฝ ์—ด: ๋น„์œจ 7
1222
+ with gr.Column(scale=7, elem_classes="panel"):
1223
+ gr.HTML('<div class="section-title"><i class="fas fa-image"></i> ํ•„ํ„ฐ ์ ์šฉ ๊ฒฐ๊ณผ</div>')
1224
+ # ์ฒ˜๋ฆฌ๋œ ์ด๋ฏธ์ง€ ์ถœ๋ ฅ
1225
+ filter_output_image = gr.Image(type="pil", label="์ฒ˜๋ฆฌ๋œ ์ด๋ฏธ์ง€", elem_classes="image-container")
1226
+
1227
+ # ๋ณ€ํ™˜๋œ ์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ ๋ฒ„ํŠผ
1228
+ with gr.Row():
1229
+ gr.HTML('<div class="section-title"><i class="fas fa-download"></i> ์ด๋ฏธ์ง€ ์ €์žฅ</div>')
1230
+ download_button = gr.Button("JPG๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ", elem_classes="custom-button primary")
1231
+ download_output = gr.File(label="JPG ์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ")
1232
+
1233
+ # ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜ ์—ฐ๊ฒฐ
1234
+ inputs = [
1235
+ filter_input_image,
1236
+ brightness_slider,
1237
+ contrast_slider,
1238
+ saturation_slider,
1239
+ temperature_slider,
1240
+ tint_slider,
1241
+ exposure_slider,
1242
+ vibrance_slider,
1243
+ color_mixer_blues_slider,
1244
+ shadows_slider
1245
+ ]
1246
+
1247
+ input_components = [
1248
+ brightness_slider,
1249
+ contrast_slider,
1250
+ saturation_slider,
1251
+ temperature_slider,
1252
+ tint_slider,
1253
+ exposure_slider,
1254
+ vibrance_slider,
1255
+ color_mixer_blues_slider,
1256
+ shadows_slider
1257
+ ]
1258
+
1259
+ for input_component in input_components:
1260
+ input_component.change(
1261
+ fn=process_image,
1262
+ inputs=inputs,
1263
+ outputs=filter_output_image
1264
+ )
1265
+
1266
+ filter_input_image.change(
1267
+ fn=lambda x, *args: process_image(x, *args) if x is not None else None,
1268
+ inputs=inputs,
1269
+ outputs=filter_output_image
1270
+ )
1271
+
1272
+ # ๋‹ค์šด๋กœ๋“œ ๋ฒ„ํŠผ ๊ธฐ๋Šฅ
1273
+ download_button.click(
1274
+ fn=download_image,
1275
+ inputs=[filter_output_image, filter_input_image],
1276
+ outputs=download_output
1277
+ )
1278
 
1279
  # ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
1280
  image_change_btn1.click(