File size: 9,304 Bytes
6ac308a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
"""
Image Enhancer App
------------------
Aplikasi berbasis Gradio untuk meningkatkan kualitas gambar dengan berbagai teknik pemrosesan citra
seperti perbaikan resolusi, penajaman, dan penghilangan noise. 
Dapat digunakan secara lokal maupun sebagai web-app AI image enhancement.

Created by _drat | 2025
"""

# Import library standar dan eksternal yang dibutuhkan
import os
import subprocess
import spaces  # Library dari HuggingFace untuk GPU management & dekorator
import torch   # Library untuk deep learning, cek GPU
import cv2     # OpenCV untuk pengolahan gambar
import uuid    # Untuk generate nama file unik
import gradio as gr # Untuk membuat UI web berbasis Python
import numpy as np  # Operasi numerik, termasuk array

from PIL import Image   # Untuk memproses dan menyimpan gambar
# Import arsitektur model dan utilitas untuk enhancement & upscaling
from basicsr.archs.srvgg_arch import SRVGGNetCompact
from gfpgan.utils import GFPGANer
from realesrgan.utils import RealESRGANer

import warnings
warnings.filterwarnings("ignore")

# Fungsi untuk menjalankan command shell (misal: wget file model)
def runcmd(cmd, verbose = False):
    process = subprocess.Popen(
        cmd,
        stdout = subprocess.PIPE,
        stderr = subprocess.PIPE,
        text = True,
        shell = True
    )
    std_out, std_err = process.communicate()
    if verbose:
        print(std_out.strip(), std_err)
    pass

# Pastikan model AI (GFPGAN dan RealESRGAN) sudah terdownload. Jika belum, otomatis download.
if not os.path.exists('GFPGANv1.4.pth'):
    runcmd("wget https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth -P .")
if not os.path.exists('realesr-general-x4v3.pth'):
    runcmd("wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.5.0/realesr-general-x4v3.pth -P .")

# Inisialisasi model Real-ESRGAN untuk upscaling gambar
model = SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=32, upscale=4, act_type='prelu')
model_path = 'realesr-general-x4v3.pth'
half = True if torch.cuda.is_available() else False  # Pakai mode half-precision jika ada GPU (lebih cepat)
upsampler = RealESRGANer(
    scale=4, model_path=model_path, model=model, 
    tile=0, tile_pad=10, pre_pad=0, half=half
)

# Fungsi utama untuk enhance gambar (dipanggil saat tombol di UI ditekan)
@spaces.GPU(duration=15)
def enhance_image(
    input_image: Image,      # Gambar input dari user (PIL Image)
    scale: int,              # Skala upscaling (misal: 2x, 4x)
    enhance_mode: str,       # Mode enhance: face saja, image saja, atau keduanya
):
    only_face = enhance_mode == "Only Face Enhance"
    
    # Pilih mode enhancer: hanya wajah, hanya gambar, atau kombinasi
    if enhance_mode == "Only Face Enhance":
        face_enhancer = GFPGANer(
            model_path='GFPGANv1.4.pth', upscale=scale, 
            arch='clean', channel_multiplier=2
        )
    elif enhance_mode == "Only Image Enhance":
        face_enhancer = None  # Tidak enhance wajah, hanya upscaling gambar saja
    else:
        face_enhancer = GFPGANer(
            model_path='GFPGANv1.4.pth', upscale=scale, 
            arch='clean', channel_multiplier=2, bg_upsampler=upsampler
        )
    
    # Konversi gambar input ke format BGR (OpenCV)
    img = cv2.cvtColor(np.array(input_image), cv2.COLOR_RGB2BGR)
    h, w = img.shape[0:2]

    # Optional: perbesar gambar jika terlalu kecil (kurang dari 300px)
    if h < 300:
        img = cv2.resize(img, (w * 2, h * 2), interpolation=cv2.INTER_LANCZOS4)
    
    # Proses enhance gambar (tergantung mode)
    if face_enhancer is not None:
        # Enhance wajah (GFPGAN), output gambar hasil enhancement
        _, _, output = face_enhancer.enhance(
            img, has_aligned=False, only_center_face=only_face, paste_back=True
        )
    else:
        # Hanya upscaling image (tanpa enhance wajah)
        output, _ = upsampler.enhance(img, outscale=scale)

    # --- Optional resize (tidak digunakan)
    # if scale != 2:
    #     interpolation = cv2.INTER_AREA if scale < 2 else cv2.INTER_LANCZOS4
    #     h, w = img.shape[0:2]
    #     output = cv2.resize(output, (int(w * scale / 2), int(h * scale / 2)), interpolation=interpolation)
    
    # Batasi hasil enhance agar tidak lebih dari 3480px (biar aman dan efisien)
    h, w = output.shape[0:2]
    max_size = 3480
    if h > max_size:
        w = int(w * max_size / h)
        h = max_size
    if w > max_size:
        h = int(h * max_size / w)
        w = max_size
    
    # Resize hasil akhir
    output = cv2.resize(output, (w, h), interpolation=cv2.INTER_LANCZOS4)

    # Konversi kembali ke RGB & PIL Image (untuk output Gradio)
    enhanced_image = Image.fromarray(cv2.cvtColor(output, cv2.COLOR_BGR2RGB))
    
    # Simpan gambar hasil enhance ke folder output dengan nama unik
    tmpPrefix = "/tmp/gradio/"
    extension = 'png'
    # targetDir = f"{tmpPrefix}output/"
    targetDir = "output/"
    if not os.path.exists(targetDir):
        os.makedirs(targetDir)

    enhanced_path = f"{targetDir}{uuid.uuid4()}.{extension}"
    enhanced_image.save(enhanced_path, quality=100)
        
    return enhanced_image, enhanced_path  # Return: image untuk preview dan path file untuk download


#
# DEMO DI SINI
#

def create_demo() -> gr.Blocks:
    with gr.Blocks() as demo:
        # Feature Image dengan border subtle & shadow
        gr.HTML(
            """
            <div style='display:flex; justify-content:center;'>
                <img src='https://i.ibb.co/jkkT7MZQ/feature-image-enhancer.jpg' 
                     alt='Feature Image' 
                     style='height:200px; width:auto; border-radius:24px; box-shadow:0 4px 18px #ffa07430; border:2.5px solid #ffe0b3;' 
                     id='feature-image'/>
            </div>
            """
        )
        # Judul & Tagline dengan emoji & gradient text
        gr.Markdown("""
            <div style="text-align:center; margin-top: -10px; margin-bottom: 14px;">
                <span style="font-size:2.1rem; font-family:'Quicksand',sans-serif; font-weight:800; background: linear-gradient(90deg,#d84040,#ff914d 60%); -webkit-background-clip: text; color:transparent; display:inline-block;">
                    <span style="vertical-align:middle;">๐Ÿ“ธ</span> Image Enhancer <b>Pro</b> <span style="font-size:1.1em;vertical-align:middle;">โœจ</span>
                </span><br>
                <span style="font-size:1.12rem; color:#d84040; font-family:'Inter',sans-serif;">
                    <span style="vertical-align:middle;">๐Ÿค–</span> Foto blur? Jadikan jernih & tajam pakai AI! 
                </span>
            </div>
        """)

        # Input dan Output dalam card, dengan icon pada title
        with gr.Row():
            with gr.Column(scale=1):
                with gr.Group(elem_id="input-card"):
                    gr.Markdown("<div class='card-title'><span style='font-size:1.3em;vertical-align:middle;'>๐Ÿ–ผ๏ธ</span> <b>Gambar Asli</b></div>")
                    input_image = gr.Image(label="", type="pil", elem_id="input-image", show_label=False)
                    gr.Markdown("<div class='hint'><span style='font-size:1.1em;'>โฌ†๏ธ</span> Upload foto format <b>JPG/PNG</b>, max 5MB</div>")
            with gr.Column(scale=1):
                with gr.Group(elem_id="output-card"):
                    gr.Markdown("<div class='card-title'><span style='font-size:1.3em;vertical-align:middle;'>๐ŸŒˆ</span> <b>Hasil AI Enhance</b></div>")
                    output_image = gr.Image(label="", type="pil", interactive=False, elem_id="output-image", show_label=False)
                    enhance_image_path = gr.File(label="โฌ‡๏ธ Download (.png)", interactive=False, elem_id="download-btn")
                    gr.Markdown("""
                        <div class='hint' style="color:#ff914d;"><span style='font-size:1.2em;'>๐Ÿ’ก</span> Klik untuk download hasilnya!</div>
                    """)

        # Kontrol dengan ikon pada label
        with gr.Group(elem_id="control-card"):
            with gr.Row():
                scale = gr.Slider(
                    minimum=1,
                    maximum=4,
                    value=2,
                    step=1,
                    label="๐Ÿ”Ž Upscale x",
                    elem_id="scale-slider"
                )
                enhance_mode = gr.Dropdown(
                    label="๐Ÿ› ๏ธ Mode Enhance",
                    choices=[
                        "Only Face Enhance",
                        "Only Image Enhance",
                        "Face Enhance + Image Enhance",
                    ],
                    value="Face Enhance + Image Enhance",
                    elem_id="mode-dropdown"
                )
                g_btn = gr.Button("๐Ÿš€ Enhance Sekarang!", elem_id="enhance-btn", size="lg")

        g_btn.click(
            fn=enhance_image,
            inputs=[input_image, scale, enhance_mode],
            outputs=[output_image, enhance_image_path],
        )
        # Footer dengan ikon & sentuhan branding
        # Tambahkan footer di bagian bawah
        gr.HTML("""
            <footer id="footer">
                Transfer Energi Semesta Digital ยฉ 2024 | ๐Ÿ‡ฎ๐Ÿ‡ฉ Untuk Indonesia Jaya!
            </footer>
            """)

    return demo