alx-ai syedusama5556 commited on
Commit
73110c5
0 Parent(s):

Duplicate from syedusama5556/Real-ESRGAN-Demo

Browse files

Co-authored-by: Syed Usama Ahmad <syedusama5556@users.noreply.huggingface.co>

Files changed (4) hide show
  1. .gitattributes +31 -0
  2. README.md +13 -0
  3. app.py +237 -0
  4. requirements.txt +11 -0
.gitattributes ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ *.ftz filter=lfs diff=lfs merge=lfs -text
6
+ *.gz filter=lfs diff=lfs merge=lfs -text
7
+ *.h5 filter=lfs diff=lfs merge=lfs -text
8
+ *.joblib filter=lfs diff=lfs merge=lfs -text
9
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
10
+ *.model filter=lfs diff=lfs merge=lfs -text
11
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
12
+ *.npy filter=lfs diff=lfs merge=lfs -text
13
+ *.npz filter=lfs diff=lfs merge=lfs -text
14
+ *.onnx filter=lfs diff=lfs merge=lfs -text
15
+ *.ot filter=lfs diff=lfs merge=lfs -text
16
+ *.parquet filter=lfs diff=lfs merge=lfs -text
17
+ *.pickle filter=lfs diff=lfs merge=lfs -text
18
+ *.pkl filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pt filter=lfs diff=lfs merge=lfs -text
21
+ *.pth filter=lfs diff=lfs merge=lfs -text
22
+ *.rar filter=lfs diff=lfs merge=lfs -text
23
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
24
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
25
+ *.tflite filter=lfs diff=lfs merge=lfs -text
26
+ *.tgz filter=lfs diff=lfs merge=lfs -text
27
+ *.wasm filter=lfs diff=lfs merge=lfs -text
28
+ *.xz filter=lfs diff=lfs merge=lfs -text
29
+ *.zip filter=lfs diff=lfs merge=lfs -text
30
+ *.zst filter=lfs diff=lfs merge=lfs -text
31
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Real-ESRGAN Demo for Image Restoration and Upscaling
3
+ emoji: 🖼️
4
+ colorFrom: blue
5
+ colorTo: indigo
6
+ sdk: gradio
7
+ sdk_version: 3.3.1
8
+ app_file: app.py
9
+ pinned: true
10
+ duplicated_from: syedusama5556/Real-ESRGAN-Demo
11
+ ---
12
+
13
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import cv2
3
+ import numpy
4
+ import os
5
+ import random
6
+ from basicsr.archs.rrdbnet_arch import RRDBNet
7
+ from basicsr.utils.download_util import load_file_from_url
8
+
9
+ from realesrgan import RealESRGANer
10
+ from realesrgan.archs.srvgg_arch import SRVGGNetCompact
11
+ from fastapi import FastAPI
12
+
13
+ # base path
14
+ CUSTOM_PATH = "/gradio"
15
+
16
+ app = FastAPI()
17
+
18
+ last_file = None
19
+ img_mode = "RGBA"
20
+
21
+ @app.get("/")
22
+ def read_main():
23
+ return {"message": "This is your main app"}
24
+
25
+
26
+ def realesrgan(img, model_name, denoise_strength, face_enhance, outscale):
27
+ """Real-ESRGAN function to restore (and upscale) images.
28
+ """
29
+ if not img:
30
+ return
31
+
32
+ # Define model parameters
33
+ if model_name == 'RealESRGAN_x4plus': # x4 RRDBNet model
34
+ model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=4)
35
+ netscale = 4
36
+ file_url = ['https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth']
37
+ elif model_name == 'RealESRNet_x4plus': # x4 RRDBNet model
38
+ model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=4)
39
+ netscale = 4
40
+ file_url = ['https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.1/RealESRNet_x4plus.pth']
41
+ elif model_name == 'RealESRGAN_x4plus_anime_6B': # x4 RRDBNet model with 6 blocks
42
+ model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=6, num_grow_ch=32, scale=4)
43
+ netscale = 4
44
+ file_url = ['https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth']
45
+ elif model_name == 'RealESRGAN_x2plus': # x2 RRDBNet model
46
+ model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=2)
47
+ netscale = 2
48
+ file_url = ['https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.1/RealESRGAN_x2plus.pth']
49
+ elif model_name == 'realesr-general-x4v3': # x4 VGG-style model (S size)
50
+ model = SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=32, upscale=4, act_type='prelu')
51
+ netscale = 4
52
+ file_url = [
53
+ 'https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.5.0/realesr-general-wdn-x4v3.pth',
54
+ 'https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.5.0/realesr-general-x4v3.pth'
55
+ ]
56
+
57
+ # Determine model paths
58
+ model_path = os.path.join('weights', model_name + '.pth')
59
+ if not os.path.isfile(model_path):
60
+ ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
61
+ for url in file_url:
62
+ # model_path will be updated
63
+ model_path = load_file_from_url(
64
+ url=url, model_dir=os.path.join(ROOT_DIR, 'weights'), progress=True, file_name=None)
65
+
66
+ # Use dni to control the denoise strength
67
+ dni_weight = None
68
+ if model_name == 'realesr-general-x4v3' and denoise_strength != 1:
69
+ wdn_model_path = model_path.replace('realesr-general-x4v3', 'realesr-general-wdn-x4v3')
70
+ model_path = [model_path, wdn_model_path]
71
+ dni_weight = [denoise_strength, 1 - denoise_strength]
72
+
73
+ # Restorer Class
74
+ upsampler = RealESRGANer(
75
+ scale=netscale,
76
+ model_path=model_path,
77
+ dni_weight=dni_weight,
78
+ model=model,
79
+ tile=0,
80
+ tile_pad=10,
81
+ pre_pad=10,
82
+ half=False,
83
+ gpu_id=None
84
+ )
85
+
86
+ # Use GFPGAN for face enhancement
87
+ if face_enhance:
88
+ from gfpgan import GFPGANer
89
+ face_enhancer = GFPGANer(
90
+ model_path='https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth',
91
+ upscale=outscale,
92
+ arch='clean',
93
+ channel_multiplier=2,
94
+ bg_upsampler=upsampler)
95
+
96
+ # Convert the input PIL image to cv2 image, so that it can be processed by realesrgan
97
+ cv_img = numpy.array(img)
98
+ img = cv2.cvtColor(cv_img, cv2.COLOR_RGBA2BGRA)
99
+
100
+ # Apply restoration
101
+ try:
102
+ if face_enhance:
103
+ _, _, output = face_enhancer.enhance(img, has_aligned=False, only_center_face=False, paste_back=True)
104
+ else:
105
+ output, _ = upsampler.enhance(img, outscale=outscale)
106
+ except RuntimeError as error:
107
+ print('Error', error)
108
+ print('If you encounter CUDA out of memory, try to set --tile with a smaller number.')
109
+ else:
110
+ # Save restored image and return it to the output Image component
111
+ if img_mode == 'RGBA': # RGBA images should be saved in png format
112
+ extension = 'png'
113
+ else:
114
+ extension = 'jpg'
115
+
116
+ out_filename = f"output_{rnd_string(8)}.{extension}"
117
+ cv2.imwrite(out_filename, output)
118
+ global last_file
119
+ last_file = out_filename
120
+ return out_filename
121
+
122
+
123
+ def rnd_string(x):
124
+ """Returns a string of 'x' random characters
125
+ """
126
+ characters = "abcdefghijklmnopqrstuvwxyz_0123456789"
127
+ result = "".join((random.choice(characters)) for i in range(x))
128
+ return result
129
+
130
+
131
+ def reset():
132
+ """Resets the Image components of the Gradio interface and deletes
133
+ the last processed image
134
+ """
135
+ global last_file
136
+ if last_file:
137
+ print(f"Deleting {last_file} ...")
138
+ os.remove(last_file)
139
+ last_file = None
140
+ return gr.update(value=None), gr.update(value=None)
141
+
142
+
143
+ def has_transparency(img):
144
+ """This function works by first checking to see if a "transparency" property is defined
145
+ in the image's info -- if so, we return "True". Then, if the image is using indexed colors
146
+ (such as in GIFs), it gets the index of the transparent color in the palette
147
+ (img.info.get("transparency", -1)) and checks if it's used anywhere in the canvas
148
+ (img.getcolors()). If the image is in RGBA mode, then presumably it has transparency in
149
+ it, but it double-checks by getting the minimum and maximum values of every color channel
150
+ (img.getextrema()), and checks if the alpha channel's smallest value falls below 255.
151
+ https://stackoverflow.com/questions/43864101/python-pil-check-if-image-is-transparent
152
+ """
153
+ if img.info.get("transparency", None) is not None:
154
+ return True
155
+ if img.mode == "P":
156
+ transparent = img.info.get("transparency", -1)
157
+ for _, index in img.getcolors():
158
+ if index == transparent:
159
+ return True
160
+ elif img.mode == "RGBA":
161
+ extrema = img.getextrema()
162
+ if extrema[3][0] < 255:
163
+ return True
164
+ return False
165
+
166
+
167
+ def image_properties(img):
168
+ """Returns the dimensions (width and height) and color mode of the input image and
169
+ also sets the global img_mode variable to be used by the realesrgan function
170
+ """
171
+ global img_mode
172
+ if img:
173
+ if has_transparency(img):
174
+ img_mode = "RGBA"
175
+ else:
176
+ img_mode = "RGB"
177
+ properties = f"Width: {img.size[0]}, Height: {img.size[1]} | Color Mode: {img_mode}"
178
+ return properties
179
+
180
+
181
+ def main():
182
+ # Gradio Interface
183
+ with gr.Blocks(title="Real-ESRGAN Gradio Demo", theme="dark") as demo:
184
+
185
+ # gr.Markdown(
186
+ # """# <div align="center"> Real-ESRGAN Demo for Image Restoration and Upscaling </div>
187
+ # <div align="center"><img width="200" height="74" src="https://github.com/xinntao/Real-ESRGAN/raw/master/assets/realesrgan_logo.png"></div>
188
+
189
+ # This Gradio Demo was built as my Final Project for **CS50's Introduction to Programming with Python**.
190
+ # Please visit the [Real-ESRGAN GitHub page](https://github.com/xinntao/Real-ESRGAN) for detailed information about the project.
191
+ # """
192
+ # )
193
+
194
+ with gr.Accordion("Options/Parameters"):
195
+ with gr.Row():
196
+ model_name = gr.Dropdown(label="Real-ESRGAN inference model to be used",
197
+ choices=["RealESRGAN_x4plus", "RealESRNet_x4plus", "RealESRGAN_x4plus_anime_6B",
198
+ "RealESRGAN_x2plus", "realesr-general-x4v3"],
199
+ value="realesr-general-x4v3", show_label=True)
200
+ denoise_strength = gr.Slider(label="Denoise Strength (Used only with the realesr-general-x4v3 model)",
201
+ minimum=0, maximum=1, step=0.1, value=0.5)
202
+ outscale = gr.Slider(label="Image Upscaling Factor",
203
+ minimum=1, maximum=10, step=1, value=2, show_label=True)
204
+ face_enhance = gr.Checkbox(label="Face Enhancement using GFPGAN (Doesn't work for anime images)",
205
+ value=False, show_label=True)
206
+
207
+ with gr.Row():
208
+ with gr.Group():
209
+ input_image = gr.Image(label="Source Image", type="pil", image_mode="RGBA")
210
+ input_image_properties = gr.Textbox(label="Image Properties", max_lines=1)
211
+ output_image = gr.Image(label="Restored Image", image_mode="RGBA")
212
+ with gr.Row():
213
+ restore_btn = gr.Button("Restore Image")
214
+ reset_btn = gr.Button("Reset")
215
+
216
+ # Event listeners:
217
+ input_image.change(fn=image_properties, inputs=input_image, outputs=input_image_properties)
218
+ restore_btn.click(fn=realesrgan,
219
+ inputs=[input_image, model_name, denoise_strength, face_enhance, outscale],
220
+ outputs=output_image,api_name="restore")
221
+ reset_btn.click(fn=reset, inputs=[], outputs=[output_image, input_image])
222
+ # reset_btn.click(None, inputs=[], outputs=[input_image], _js="() => (null)\n")
223
+ # Undocumented method to clear a component's value using Javascript
224
+
225
+ gr.Markdown(
226
+ """*Please note that support for animated GIFs is not yet implemented. Should an animated GIF is chosen for restoration,
227
+ the demo will output only the first frame saved in PNG format (to preserve probable transparency).*
228
+ """
229
+ )
230
+
231
+ demo.launch()
232
+ app = gr.mount_gradio_app(app, gr, path=CUSTOM_PATH)
233
+
234
+
235
+
236
+ if __name__ == "__main__":
237
+ main()
requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ torch
2
+ torchvision
3
+ numpy
4
+ opencv-python
5
+ Pillow
6
+ basicsr
7
+ facexlib
8
+ gfpgan
9
+ tqdm
10
+ gradio
11
+ realesrgan