ParamDev commited on
Commit
3a4f839
·
verified ·
1 Parent(s): c5c14d9

Initial upload of files

Browse files
Files changed (5) hide show
  1. .gitattributes +1 -35
  2. .gitignore +13 -0
  3. README.md +112 -6
  4. app.py +203 -0
  5. requirements.txt +5 -0
.gitattributes CHANGED
@@ -1,35 +1 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ demo.png filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.gitignore ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ignore Python bytecode files
2
+ __pycache__/
3
+ *.py[cod]
4
+
5
+ # Ignore virtual environments
6
+ venv/
7
+ .venv/
8
+
9
+ # Ignore API keys and configuration files
10
+ .env
11
+
12
+ # Ignore model files and other large files
13
+ model/
README.md CHANGED
@@ -1,12 +1,118 @@
1
  ---
2
- title: SAT ELITE
3
- emoji: 🐢
4
- colorFrom: green
5
- colorTo: purple
6
  sdk: gradio
7
- sdk_version: 5.39.0
8
  app_file: app.py
9
  pinned: false
 
10
  ---
 
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Real-ESRGAN Dual-Mode Image Upscaler
3
+ emoji: 🖼️
4
+ colorFrom: blue
5
+ colorTo: green
6
  sdk: gradio
7
+ sdk_version: 5.31.0
8
  app_file: app.py
9
  pinned: false
10
+ license: mit
11
  ---
12
+ # 🖼️ SpectraGAN Dual-Mode Image Upscaler
13
 
14
+ A lightweight Gradio web app to upscale any image using the Real-ESRGAN model. Simply upload your photo, choose either **Standard Upscale** (×4) or **Premium Upscale** (×8), and download the upscaled image.
15
+
16
+ ---
17
+
18
+ ## 📑 Table of Contents
19
+
20
+ 1. [Features](#features)
21
+ 2. [Project Structure](#project-structure)
22
+ 3. [Prerequisites](#prerequisites)
23
+ 4. [Installation](#installation)
24
+ 5. [Running Locally](#running-locally)
25
+ 6. [Usage](#usage)
26
+ 7. [Contributing](#contributing)
27
+ 8. [License](#license)
28
+ 9. [Author & Credits](#author--credits)
29
+
30
+ ---
31
+
32
+ ## ✨ Features
33
+
34
+ - **Standard Upscale (×4)**
35
+ Enhance image resolution by 4x for clearer and larger images.
36
+
37
+ - **Premium Upscale (×8)**
38
+ Upscales first to 4x and then resizes using bicubic interpolation for even higher resolution (8x).
39
+
40
+ - **Live Preview**
41
+ See your original and upscaled images side by side before downloading.
42
+
43
+ - **Instant Download**
44
+ Export the upscaled image as a PNG and use it immediately.
45
+
46
+ ---
47
+
48
+ ## 📁 Project Structure
49
+
50
+ ```
51
+ upscale-project/
52
+ ├── model/
53
+ │ └── Real-ESRGAN-x4plus.onnx # ONNX model for upscaling
54
+ ├── app.py # Main application file
55
+ ├── requirements.txt # List of Python dependencies
56
+ ├── .gitignore # Git ignore file to exclude unnecessary files
57
+ ├── LICENSE # License file for the project
58
+ └── README.md # Project documentation
59
+ ```
60
+
61
+ ---
62
+
63
+ ---
64
+
65
+ ## ⚙️ Prerequisites
66
+
67
+ - Python 3.10 or higher
68
+ - `git`
69
+ - A terminal / command prompt
70
+
71
+ ---
72
+
73
+ ## 🔧 Installation
74
+
75
+ 1. Clone this repository:
76
+
77
+ ```bash
78
+ git clone https://github.com/salmanalfarisi11/Upscaler_images.git
79
+ cd Upscaler_images
80
+ ```
81
+
82
+ 2. Create and activate a virtual environment:
83
+
84
+ ```bash
85
+ python -m venv .venv
86
+ source .venv/bin/activate # Linux/macOS
87
+ .venv\Scripts\activate # Windows
88
+ ```
89
+
90
+ 3. Install dependencies:
91
+
92
+ ```bash
93
+ pip install -r requirements.txt
94
+ ```
95
+
96
+ ## 🚀 Running Locally
97
+
98
+ Launch the app on your machine:
99
+
100
+ ```bash
101
+ python app.py
102
+ ```
103
+
104
+ By default, it will start on <http://127.0.0.1:7860/>. Open that URL in your browser to access the interface.
105
+
106
+ ## 🎯 Usage
107
+
108
+ 1. **Upload Photo** via the left panel.
109
+ 2. **Choose a Mode**:
110
+ - Click **Standard Upscale (×4)** for a 4x resolution increase.
111
+ - Click **Premium Upscale (×8)** for an 8x resolution increase.
112
+ 3. Preview your result on the right side.
113
+ 4. Click **Download PNG** to save the upscaled image.
114
+
115
+ ## Acknowledgements
116
+
117
+ This project uses the Real-ESRGAN model developed by Xintao Wang.
118
+ The model is available under the BSD 3-Clause License.
app.py ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import math
3
+ import uuid
4
+ import numpy as np
5
+ import onnxruntime as ort
6
+ from PIL import Image
7
+ import gradio as gr
8
+ import tempfile
9
+ import requests
10
+
11
+
12
+ MODEL_DIR = "model"
13
+ MODEL_X2_PATH = os.path.join(MODEL_DIR, "Real-ESRGAN_x2plus.onnx")
14
+ MODEL_X4_PATH = os.path.join(MODEL_DIR, "Real-ESRGAN-x4plus.onnx")
15
+
16
+
17
+ FILE_ID_X2 = "15xmXXZNH2wMyeQv4ie5hagT7eWK9MgP6"
18
+ FILE_ID_X4 = "1wDBHad9RCJgJDGsPdapLYl3cr8j-PMJ6"
19
+
20
+ def download_from_drive(file_id: str, dest_path: str):
21
+
22
+ URL = "https://drive.google.com/uc?export=download"
23
+ session = requests.Session()
24
+
25
+
26
+ response = session.get(URL, params={"id": file_id}, stream=True)
27
+ token = None
28
+ for key, value in response.cookies.items():
29
+ if key.startswith('download_warning'):
30
+ token = value
31
+ break
32
+
33
+
34
+ if token:
35
+ params = {"id": file_id, "confirm": token}
36
+ response = session.get(URL, params=params, stream=True)
37
+
38
+
39
+ os.makedirs(os.path.dirname(dest_path), exist_ok=True)
40
+ with open(dest_path, "wb") as f:
41
+ for chunk in response.iter_content(chunk_size=32768):
42
+ if chunk:
43
+ f.write(chunk)
44
+ print(f"Model telah diunduh dan disimpan di {dest_path}")
45
+ return dest_path
46
+
47
+
48
+ if not os.path.isfile(MODEL_X2_PATH):
49
+ download_from_drive(FILE_ID_X2, MODEL_X2_PATH)
50
+
51
+ # Unduh model ×4
52
+ if not os.path.isfile(MODEL_X4_PATH):
53
+ download_from_drive(FILE_ID_X4, MODEL_X4_PATH)
54
+
55
+
56
+ sess_opts = ort.SessionOptions()
57
+ sess_opts.intra_op_num_threads = 2
58
+ sess_opts.inter_op_num_threads = 2
59
+
60
+ session_x2 = ort.InferenceSession(MODEL_X2_PATH, sess_options=sess_opts, providers=["CPUExecutionProvider"])
61
+ session_x4 = ort.InferenceSession(MODEL_X4_PATH, sess_options=sess_opts, providers=["CPUExecutionProvider"])
62
+
63
+
64
+ input_meta_x2 = session_x2.get_inputs()[0]
65
+ _, _, H_in_x2, W_in_x2 = tuple(input_meta_x2.shape)
66
+ H_in_x2, W_in_x2 = int(H_in_x2), int(W_in_x2)
67
+
68
+ input_meta_x4 = session_x4.get_inputs()[0]
69
+ _, _, H_in_x4, W_in_x4 = tuple(input_meta_x4.shape)
70
+ H_in_x4, W_in_x4 = int(H_in_x4), int(W_in_x4)
71
+
72
+
73
+ dummy_x2 = np.zeros((1, 3, H_in_x2, W_in_x2), dtype=np.float32)
74
+ dummy_out_x2 = session_x2.run(None, {input_meta_x2.name: dummy_x2})[0]
75
+ _, _, H_out_x2, W_out_x2 = dummy_out_x2.shape
76
+ SCALE_X2 = H_out_x2 // H_in_x2
77
+ if SCALE_X2 != 2:
78
+ raise RuntimeError(f"Model ×2 menghasilkan scale = {SCALE_X2}, bukan 2")
79
+
80
+ dummy_x4 = np.zeros((1, 3, H_in_x4, W_in_x4), dtype=np.float32)
81
+ dummy_out_x4 = session_x4.run(None, {input_meta_x4.name: dummy_x4})[0]
82
+ _, _, H_out_x4, W_out_x4 = dummy_out_x4.shape
83
+ SCALE_X4 = H_out_x4 // H_in_x4
84
+ if SCALE_X4 != 4:
85
+ raise RuntimeError(f"Model ×4 menghasilkan scale = {SCALE_X4}, bukan 4")
86
+
87
+
88
+ def run_tile_x2(tile_np: np.ndarray) -> np.ndarray:
89
+ patch_nchw = np.transpose(tile_np, (2, 0, 1))[None, ...]
90
+ out_nchw = session_x2.run(None, {input_meta_x2.name: patch_nchw})[0]
91
+ out_nchw = np.squeeze(out_nchw, axis=0)
92
+ out_hwc = np.transpose(out_nchw, (1, 2, 0))
93
+ return out_hwc
94
+
95
+ def run_tile_x4(tile_np: np.ndarray) -> np.ndarray:
96
+ patch_nchw = np.transpose(tile_np, (2, 0, 1))[None, ...]
97
+ out_nchw = session_x4.run(None, {input_meta_x4.name: patch_nchw})[0]
98
+ out_nchw = np.squeeze(out_nchw, axis=0)
99
+ out_hwc = np.transpose(out_nchw, (1, 2, 0))
100
+ return out_hwc
101
+
102
+
103
+ def tile_upscale(input_img: Image.Image, scale: int, max_dim=1024):
104
+ if scale == 2:
105
+ H_in, W_in, run_tile, SCALE = H_in_x2, W_in_x2, run_tile_x2, SCALE_X2
106
+ else:
107
+ H_in, W_in, run_tile, SCALE = H_in_x4, W_in_x4, run_tile_x4, SCALE_X4
108
+
109
+
110
+ w, h = input_img.size
111
+ if w > max_dim or h > max_dim:
112
+ scale_factor = max_dim / float(max(w, h))
113
+ new_w = int(w * scale_factor)
114
+ new_h = int(h * scale_factor)
115
+ input_img = input_img.resize((new_w, new_h), Image.LANCZOS)
116
+
117
+ img_rgb = input_img.convert("RGB")
118
+ arr = np.array(img_rgb).astype(np.float32) / 255.0
119
+ h_orig, w_orig, _ = arr.shape
120
+
121
+ tiles_h = math.ceil(h_orig / H_in)
122
+ tiles_w = math.ceil(w_orig / W_in)
123
+ pad_h = tiles_h * H_in - h_orig
124
+ pad_w = tiles_w * W_in - w_orig
125
+
126
+ arr_padded = np.pad(arr, ((0, pad_h), (0, pad_w), (0, 0)), mode="reflect")
127
+ out_h = tiles_h * H_in * SCALE
128
+ out_w = tiles_w * W_in * SCALE
129
+ out_arr = np.zeros((out_h, out_w, 3), dtype=np.float32)
130
+
131
+ for i in range(tiles_h):
132
+ for j in range(tiles_w):
133
+ y0, x0 = i * H_in, j * W_in
134
+ tile = arr_padded[y0:y0+H_in, x0:x0+W_in, :]
135
+ up_tile = run_tile(tile)
136
+ oy0, ox0 = i * H_in * SCALE, j * W_in * SCALE
137
+ out_arr[oy0:oy0 + H_in * SCALE, ox0:ox0 + W_in * SCALE, :] = up_tile
138
+
139
+ final_arr = out_arr[0:h_orig * SCALE, 0:w_orig * SCALE, :]
140
+ final_arr = np.clip(final_arr, 0.0, 1.0)
141
+ final_uint8 = (final_arr * 255.0).round().astype(np.uint8)
142
+ final_pil = Image.fromarray(final_uint8)
143
+
144
+ tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
145
+ final_pil.save(tmp.name, format="PNG")
146
+ tmp.close()
147
+ return final_pil, tmp.name
148
+
149
+
150
+ def upscale_x2(input_img: Image.Image):
151
+ return tile_upscale(input_img, scale=2)
152
+
153
+ def standard_upscale(input_img: Image.Image):
154
+ return tile_upscale(input_img, scale=4)
155
+
156
+ def premium_upscale(input_img: Image.Image):
157
+ final_4x, _ = tile_upscale(input_img, scale=4)
158
+ w_orig, h_orig = input_img.size
159
+ target_size = (w_orig * 8, h_orig * 8)
160
+ final_8x = final_4x.resize(target_size, resample=Image.LANCZOS)
161
+ tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
162
+ final_8x.save(tmp.name, format="PNG")
163
+ tmp.close()
164
+ return final_8x, tmp.name
165
+
166
+
167
+ css = """
168
+ #x2-btn {
169
+ background-color: lightgreen !important;
170
+ color: black !important;
171
+ }
172
+ #premium-btn {
173
+ background-color: gold !important;
174
+ color: black !important;
175
+ }
176
+ """
177
+
178
+
179
+ with gr.Blocks(css=css, title="SpectraGAN Triple-Mode Upscaler") as demo:
180
+ gr.Markdown(
181
+ """
182
+ # SpectraGAN Upscaler
183
+ **Upscale (×2)**, **Standard Upscale (×4)** atau **Premium Upscale 🚀 (×8)**.
184
+
185
+ """
186
+ )
187
+
188
+ with gr.Row():
189
+ inp_image = gr.Image(type="pil", label="Upload Source Image")
190
+
191
+ with gr.Row():
192
+ btn_x2 = gr.Button("Upscale (×2)", elem_id="x2-btn")
193
+ btn_std = gr.Button("Standard Upscale (×4)", variant="primary", elem_id="std-btn")
194
+ btn_prem = gr.Button("Premium Upscale 🚀 (×8)", elem_id="premium-btn")
195
+
196
+ out_preview = gr.Image(type="pil", label="Upscaled Preview")
197
+ out_download = gr.DownloadButton("⬇️ Download PNG", visible=True)
198
+
199
+ btn_x2.click(fn=upscale_x2, inputs=inp_image, outputs=[out_preview, out_download])
200
+ btn_std.click(fn=standard_upscale, inputs=inp_image, outputs=[out_preview, out_download])
201
+ btn_prem.click(fn=premium_upscale, inputs=inp_image, outputs=[out_preview, out_download])
202
+
203
+ demo.launch(server_name="0.0.0.0", server_port=7860)
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ onnxruntime # ONNX inference engine (CPU)
2
+ numpy # Array manipulation
3
+ Pillow # Image I/O
4
+ gradio>=3.0 # Web UI
5
+ requests