File size: 5,820 Bytes
eed6196
f89d48f
6b887c2
 
40510cd
673e0b5
c9a5131
6b887c2
d59a3eb
6b887c2
d59a3eb
6b887c2
 
 
 
 
 
 
 
 
 
 
2f92abc
 
 
 
6b887c2
2f92abc
 
 
6b887c2
2f92abc
6b887c2
 
2f92abc
 
 
6b887c2
 
673e0b5
28e29a9
6b887c2
 
 
673e0b5
 
 
 
 
28e29a9
6b887c2
673e0b5
 
229d6fe
673e0b5
229d6fe
 
673e0b5
 
 
 
 
229d6fe
 
673e0b5
 
6b887c2
28e29a9
6b887c2
673e0b5
 
 
93e3a29
673e0b5
 
 
 
 
 
 
 
93e3a29
673e0b5
93e3a29
673e0b5
 
 
 
 
 
 
93e3a29
673e0b5
93e3a29
673e0b5
 
 
 
 
93e3a29
673e0b5
6b887c2
 
 
 
 
 
673e0b5
6b887c2
28e29a9
 
 
6b887c2
 
 
 
 
 
 
 
 
 
40510cd
93e3a29
40510cd
 
6b887c2
40510cd
6b887c2
2f92abc
6b887c2
673e0b5
f89d48f
2f92abc
 
6b887c2
 
 
 
 
 
 
28fd0ef
6b887c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c9a5131
f89d48f
6b887c2
 
 
f89d48f
 
6b887c2
391d859
93e3a29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import gradio as gr
from PIL import Image, ImageEnhance, ImageOps, ImageFilter
import io
import base64
import tempfile
import os

def image_to_base64(img):
    """
    PIL ์ด๋ฏธ์ง€๋ฅผ base64 ์ธ์ฝ”๋”ฉ๋œ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
    """
    buffered = io.BytesIO()
    img.save(buffered, format="JPEG")
    img_bytes = buffered.getvalue()
    img_base64 = base64.b64encode(img_bytes).decode()
    return img_base64

def transform_image(image, contrast, brightness, blur):
    """
    ์ด๋ฏธ์ง€๋ฅผ ํ‘๋ฐฑ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์กฐ์ ˆํ•œ ๋Œ€๋น„, ๋ฐ๊ธฐ, ํ๋ฆผ ํšจ๊ณผ๋ฅผ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
    """
    # ํ‘๋ฐฑ ๋ณ€ํ™˜
    bw_image = ImageOps.grayscale(image)
    
    # ๋Œ€๋น„ ํ–ฅ์ƒ
    enhancer = ImageEnhance.Contrast(bw_image)
    bw_image = enhancer.enhance(contrast)
    
    # ๋ฐ๊ธฐ ์กฐ์ ˆ
    enhancer = ImageEnhance.Brightness(bw_image)
    bw_image = enhancer.enhance(brightness)
    
    # ํ๋ฆผ ํšจ๊ณผ ์ถ”๊ฐ€
    bw_image = bw_image.filter(ImageFilter.GaussianBlur(radius=blur))
    
    return bw_image

def generate_comparison_html(original_base64, transformed_base64):
    """
    ๋ณ€ํ™˜๋œ ์ด๋ฏธ์ง€์™€ ์›๋ณธ ์ด๋ฏธ์ง€๋ฅผ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜ํ‰ ์Šฌ๋ผ์ด๋” HTML์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    ๋ณ€ํ™˜๋œ ์ด๋ฏธ์ง€๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์Šฌ๋ผ์ด๋”๋ฅผ ์›€์ง์—ฌ ์›๋ณธ ์ด๋ฏธ์ง€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    """
    html = f"""
    <div style="position: relative; width: 100%; max-width: 600px; margin: auto;">
      <!-- ๋ณ€ํ™˜๋œ ์ด๋ฏธ์ง€ (๋ฐฐ๊ฒฝ) -->
      <img src="data:image/jpeg;base64,{transformed_base64}" style="width: 100%; display: block;">
      
      <!-- ์›๋ณธ ์ด๋ฏธ์ง€ (์˜ค๋ฒ„๋ ˆ์ด) -->
      <div id="overlay" style="position: absolute; top:0; left:0; width:50%; overflow: hidden; height:100%;">
        <img src="data:image/jpeg;base64,{original_base64}" style="width: 100%;">
      </div>
      
      <!-- ์Šฌ๋ผ์ด๋” -->
      <input type="range" min="0" max="100" value="50" 
             oninput="document.getElementById('overlay').style.width = this.value + '%';" 
             style="
                position: absolute;
                bottom: 10px;
                left: 50%;
                transform: translateX(-50%);
                width: 80%;
                -webkit-appearance: none;
                background: transparent;
             ">
      
      <!-- ์Šฌ๋ผ์ด๋” ๋ ˆ์ด๋ธ” -->
      <div style="text-align: center; margin-top: 10px;">
        <span>๋ณ€ํ™˜ ํ›„</span> <span style="float: right;">๋ณ€ํ™˜ ์ „</span>
      </div>
      
      <!-- ์Šฌ๋ผ์ด๋” ์Šคํƒ€์ผ๋ง -->
      <style>
        input[type=range] {{
          -webkit-appearance: none;
          width: 100%;
          height: 5px;
          background: #ddd;
          outline: none;
          opacity: 0.7;
          -webkit-transition: .2s;
          transition: opacity .2s;
        }}

        input[type=range]::-webkit-slider-thumb {{
          -webkit-appearance: none;
          appearance: none;
          width: 15px;
          height: 15px;
          background: #4CAF50;
          cursor: pointer;
          border-radius: 50%;
        }}

        input[type=range]::-moz-range-thumb {{
          width: 15px;
          height: 15px;
          background: #4CAF50;
          cursor: pointer;
          border-radius: 50%;
        }}
      </style>
    </div>
    """
    return html

def process_image(image, contrast, brightness, blur):
    """
    ์‚ฌ์šฉ์ž๊ฐ€ ์—…๋กœ๋“œํ•œ ์ด๋ฏธ์ง€๋ฅผ ๋ณ€ํ™˜ํ•˜๊ณ , ๋น„๊ต ์Šฌ๋ผ์ด๋”์™€ ๋‹ค์šด๋กœ๋“œ ๋งํฌ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    """
    if image is None:
        return "์ด๋ฏธ์ง€๊ฐ€ ์—…๋กœ๋“œ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.", None

    # ์ด๋ฏธ์ง€ ๋ณ€ํ™˜
    transformed = transform_image(image, contrast, brightness, blur)
    
    # ์ด๋ฏธ์ง€๋ฅผ base64๋กœ ๋ณ€ํ™˜
    original_base64 = image_to_base64(image)
    transformed_base64 = image_to_base64(transformed)
    
    # ๋น„๊ต ์Šฌ๋ผ์ด๋“œ HTML ์ƒ์„ฑ
    comparison_html = generate_comparison_html(original_base64, transformed_base64)
    
    # ๋ณ€ํ™˜๋œ ์ด๋ฏธ์ง€๋ฅผ ์ž„์‹œ ํŒŒ์ผ๋กœ ์ €์žฅ
    with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False, prefix="transformed_", dir="/tmp") as tmp_file:
        transformed.save(tmp_file, format="JPEG")
        tmp_file_path = tmp_file.name
    
    return comparison_html, tmp_file_path

with gr.Blocks() as demo:
    gr.Markdown("## ๐Ÿ“ธ ๋ถ„์œ„๊ธฐ ์žˆ๋Š” ํ‘๋ฐฑ ์‚ฌ์ง„ ๋ณ€ํ™˜๊ธฐ")
    gr.Markdown("์›๋ณธ ์ด๋ฏธ์ง€์™€ ๋ณ€ํ™˜๋œ ์ด๋ฏธ์ง€๋ฅผ ์Šฌ๋ผ์ด๋”๋กœ ๋น„๊ตํ•˜๊ณ , ๋ณ€ํ™˜๋œ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.")
    
    with gr.Row():
        with gr.Column():
            input_image = gr.Image(type="pil", label="๐Ÿ“ฅ ์›๋ณธ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ")
            contrast_slider = gr.Slider(
                minimum=0.5, 
                maximum=3.0, 
                step=0.1, 
                value=1.5, 
                label="๐Ÿ” ๋Œ€๋น„ ์กฐ์ ˆ"
            )
            brightness_slider = gr.Slider(
                minimum=0.5, 
                maximum=3.0, 
                step=0.1, 
                value=0.9, 
                label="๐Ÿ’ก ๋ฐ๊ธฐ ์กฐ์ ˆ"
            )
            blur_slider = gr.Slider(
                minimum=0, 
                maximum=5, 
                step=0.5, 
                value=1, 
                label="๐ŸŒซ๏ธ ํ๋ฆผ ํšจ๊ณผ"
            )
            convert_button = gr.Button("๐Ÿ”„ ๋ณ€ํ™˜ํ•˜๊ธฐ")
        with gr.Column():
            comparison = gr.HTML(label="๐Ÿ” ๋ณ€ํ™˜ ์ „ํ›„ ๋น„๊ต")
            download_link = gr.File(label="โฌ‡๏ธ JPG๋กœ ๋‹ค์šด๋กœ๋“œ")
    
    convert_button.click(
        fn=process_image,
        inputs=[input_image, contrast_slider, brightness_slider, blur_slider],
        outputs=[comparison, download_link]
    )
    
    gr.Markdown("ยฉ๏ธ 2024 ๋ถ„์œ„๊ธฐ ์žˆ๋Š” ํ‘๋ฐฑ ์‚ฌ์ง„ ๋ณ€ํ™˜๊ธฐ by OpenAI")

demo.launch()