| | 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) |
| | |
| | |
| | original_base64 = image_to_base64(image) |
| | transformed_base64 = image_to_base64(transformed) |
| | |
| | |
| | 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() |
| |
|