lucky0146 commited on
Commit
800b2d2
·
verified ·
1 Parent(s): 66755f5

Update gfpgan_cpu.py

Browse files
Files changed (1) hide show
  1. gfpgan_cpu.py +111 -87
gfpgan_cpu.py CHANGED
@@ -1,19 +1,60 @@
1
  import os
2
- import argparse
3
  import cv2
4
- import glob
5
  import numpy as np
6
  import torch
 
7
  from tqdm import tqdm
8
- from pathlib import Path
9
- from basicsr.utils import imwrite
10
 
11
- # This is a simple implementation of GFPGAN for CPU usage on Hugging Face
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  def download_model():
13
  """Download the GFPGAN model if not already present"""
14
- import urllib.request
15
- import os
16
-
17
  os.makedirs('experiments/pretrained_models', exist_ok=True)
18
  model_path = 'experiments/pretrained_models/GFPGANv1.3.pth'
19
 
@@ -27,26 +68,12 @@ def download_model():
27
 
28
  def setup_gfpgan():
29
  """Set up GFPGAN with the required dependencies"""
30
- # Install required packages if not already installed
31
- try:
32
- import basicsr
33
- except ImportError:
34
- print("Installing basicsr...")
35
- os.system('pip install basicsr')
36
-
37
- try:
38
- import facexlib
39
- except ImportError:
40
- print("Installing facexlib...")
41
- os.system('pip install facexlib')
42
-
43
- try:
44
- import gfpgan
45
- except ImportError:
46
- print("Installing GFPGAN...")
47
- os.system('pip install gfpgan')
48
 
 
49
  from gfpgan import GFPGANer
 
50
 
51
  # Download the model
52
  model_path = download_model()
@@ -54,7 +81,7 @@ def setup_gfpgan():
54
  # Initialize GFPGAN for CPU usage
55
  device = torch.device('cpu')
56
 
57
- # Set up the restorer - note we're using CPU mode with half=False
58
  restorer = GFPGANer(
59
  model_path=model_path,
60
  upscale=2,
@@ -68,10 +95,11 @@ def setup_gfpgan():
68
 
69
  def process_image(restorer, img_path, output_dir='results'):
70
  """Process a single image with GFPGAN"""
 
 
71
  os.makedirs(output_dir, exist_ok=True)
72
  os.makedirs(os.path.join(output_dir, 'restored_faces'), exist_ok=True)
73
  os.makedirs(os.path.join(output_dir, 'restored_imgs'), exist_ok=True)
74
- os.makedirs(os.path.join(output_dir, 'cmp'), exist_ok=True)
75
 
76
  # Read image
77
  img_name = os.path.basename(img_path)
@@ -82,33 +110,72 @@ def process_image(restorer, img_path, output_dir='results'):
82
 
83
  if input_img is None:
84
  print(f"Warning: Cannot read image {img_path}")
85
- return
86
 
87
  # Restore faces and background
88
- cropped_faces, restored_faces, restored_img = restorer.enhance(
89
- input_img, has_aligned=False, only_center_face=False, paste_back=True)
90
-
91
- # Save faces
92
- for idx, (cropped_face, restored_face) in enumerate(zip(cropped_faces, restored_faces)):
93
- # Save restored face
94
- save_face_name = f'{basename}_{idx:02d}.png'
95
- save_restore_path = os.path.join(output_dir, 'restored_faces', save_face_name)
96
- imwrite(restored_face, save_restore_path)
97
-
98
- # Save comparison image
99
- cmp_img = np.concatenate((cropped_face, restored_face), axis=1)
100
- imwrite(cmp_img, os.path.join(output_dir, 'cmp', f'{basename}_{idx:02d}.png'))
101
 
102
  # Save restored image
103
  if restored_img is not None:
104
  extension = ext[1:] if ext else 'png'
105
  save_restore_path = os.path.join(output_dir, 'restored_imgs', f'{basename}.{extension}')
106
  imwrite(restored_img, save_restore_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
- return os.path.join(output_dir, 'restored_imgs', f'{basename}.{extension}')
109
 
 
110
  def main():
111
- """Main function to run GFPGAN on CPU"""
 
 
112
  parser = argparse.ArgumentParser(description='GFPGAN for CPU')
113
  parser.add_argument('--input', type=str, default='inputs', help='Input image or folder')
114
  parser.add_argument('--output', type=str, default='results', help='Output folder')
@@ -133,52 +200,9 @@ def main():
133
 
134
  print(f'Results are saved in {output_dir}')
135
 
136
- # For Hugging Face Spaces (Gradio interface)
137
- def create_gradio_app():
138
- import gradio as gr
139
-
140
- restorer = setup_gfpgan()
141
-
142
- def process_image_gradio(image):
143
- # Save input image temporarily
144
- temp_input = 'temp_input.jpg'
145
- cv2.imwrite(temp_input, image[:, :, ::-1]) # Convert RGB to BGR for OpenCV
146
-
147
- # Process the image
148
- output_path = process_image(restorer, temp_input, 'results')
149
-
150
- # Read the output image
151
- restored_img = cv2.imread(output_path)
152
-
153
- # Convert back to RGB for Gradio
154
- if restored_img is not None:
155
- restored_img = restored_img[:, :, ::-1]
156
- return restored_img
157
- else:
158
- return image # Return original if processing failed
159
-
160
- # Create Gradio interface
161
- app = gr.Interface(
162
- fn=process_image_gradio,
163
- inputs=gr.Image(),
164
- outputs=gr.Image(),
165
- title="GFPGAN - Face Restoration",
166
- description="Upload an image to improve facial details with GFPGAN running on CPU"
167
- )
168
-
169
- return app
170
-
171
  if __name__ == '__main__':
172
- import sys
173
-
174
  # Check if running in a Hugging Face Space
175
  if os.getenv('SPACE_ID'):
176
- try:
177
- import gradio as gr
178
- except ImportError:
179
- os.system('pip install gradio')
180
- import gradio as gr
181
-
182
  app = create_gradio_app()
183
  app.launch()
184
  else:
 
1
  import os
 
2
  import cv2
 
3
  import numpy as np
4
  import torch
5
+ import urllib.request
6
  from tqdm import tqdm
 
 
7
 
8
+ # Fix for the torchvision import error
9
+ def fix_torchvision_issue():
10
+ """Create a workaround for the torchvision.transforms.functional_tensor issue"""
11
+ import torchvision
12
+ import sys
13
+
14
+ # Check if the problematic module exists
15
+ if not hasattr(torchvision.transforms, 'functional_tensor'):
16
+ # Create the missing module
17
+ class FunctionalTensorModule:
18
+ def rgb_to_grayscale(self, img):
19
+ # Simple implementation of rgb_to_grayscale
20
+ if len(img.shape) == 4: # batch of images
21
+ return (img[:, 0, ...] * 0.2989 + img[:, 1, ...] * 0.5870 + img[:, 2, ...] * 0.1140).unsqueeze(1)
22
+ else: # single image
23
+ return (img[0, ...] * 0.2989 + img[1, ...] * 0.5870 + img[2, ...] * 0.1140).unsqueeze(0)
24
+
25
+ # Add the module to torchvision.transforms
26
+ torchvision.transforms.functional_tensor = FunctionalTensorModule()
27
+
28
+ # Add it to sys.modules to ensure imports work
29
+ sys.modules['torchvision.transforms.functional_tensor'] = torchvision.transforms.functional_tensor
30
+
31
+ print("Added compatibility layer for torchvision.transforms.functional_tensor")
32
+
33
+ def install_dependencies():
34
+ """Install all required dependencies with specific versions to avoid conflicts"""
35
+ print("Installing dependencies...")
36
+
37
+ # Install specific versions known to work together
38
+ packages = [
39
+ "torch==1.12.1",
40
+ "torchvision==0.13.1",
41
+ "basicsr>=1.4.2",
42
+ "facexlib>=0.2.5",
43
+ "gfpgan>=1.3.8",
44
+ "opencv-python",
45
+ "tqdm"
46
+ ]
47
+
48
+ for package in packages:
49
+ os.system(f"pip install {package}")
50
+
51
+ # Fix torchvision issue after installation
52
+ fix_torchvision_issue()
53
+
54
+ print("Dependencies installed successfully")
55
+
56
  def download_model():
57
  """Download the GFPGAN model if not already present"""
 
 
 
58
  os.makedirs('experiments/pretrained_models', exist_ok=True)
59
  model_path = 'experiments/pretrained_models/GFPGANv1.3.pth'
60
 
 
68
 
69
  def setup_gfpgan():
70
  """Set up GFPGAN with the required dependencies"""
71
+ # Install dependencies if needed
72
+ install_dependencies()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
+ # Import after installing dependencies
75
  from gfpgan import GFPGANer
76
+ from basicsr.utils import imwrite
77
 
78
  # Download the model
79
  model_path = download_model()
 
81
  # Initialize GFPGAN for CPU usage
82
  device = torch.device('cpu')
83
 
84
+ # Set up the restorer - note we're using CPU mode
85
  restorer = GFPGANer(
86
  model_path=model_path,
87
  upscale=2,
 
95
 
96
  def process_image(restorer, img_path, output_dir='results'):
97
  """Process a single image with GFPGAN"""
98
+ from basicsr.utils import imwrite
99
+
100
  os.makedirs(output_dir, exist_ok=True)
101
  os.makedirs(os.path.join(output_dir, 'restored_faces'), exist_ok=True)
102
  os.makedirs(os.path.join(output_dir, 'restored_imgs'), exist_ok=True)
 
103
 
104
  # Read image
105
  img_name = os.path.basename(img_path)
 
110
 
111
  if input_img is None:
112
  print(f"Warning: Cannot read image {img_path}")
113
+ return None
114
 
115
  # Restore faces and background
116
+ try:
117
+ cropped_faces, restored_faces, restored_img = restorer.enhance(
118
+ input_img, has_aligned=False, only_center_face=False, paste_back=True)
119
+ except RuntimeError as e:
120
+ print(f"Error processing image: {e}")
121
+ return None
 
 
 
 
 
 
 
122
 
123
  # Save restored image
124
  if restored_img is not None:
125
  extension = ext[1:] if ext else 'png'
126
  save_restore_path = os.path.join(output_dir, 'restored_imgs', f'{basename}.{extension}')
127
  imwrite(restored_img, save_restore_path)
128
+ return save_restore_path
129
+
130
+ return None
131
+
132
+ def create_gradio_app():
133
+ """Create a Gradio web interface for the GFPGAN model"""
134
+ try:
135
+ import gradio as gr
136
+ except ImportError:
137
+ os.system('pip install gradio')
138
+ import gradio as gr
139
+
140
+ # Set up GFPGAN
141
+ restorer = setup_gfpgan()
142
+
143
+ def process_image_gradio(image):
144
+ if image is None:
145
+ return None
146
+
147
+ # Save input image temporarily
148
+ temp_input = 'temp_input.jpg'
149
+ cv2.imwrite(temp_input, image[:, :, ::-1]) # Convert RGB to BGR for OpenCV
150
+
151
+ # Process the image
152
+ output_path = process_image(restorer, temp_input, 'results')
153
+
154
+ # Read the output image
155
+ if output_path and os.path.exists(output_path):
156
+ restored_img = cv2.imread(output_path)
157
+ # Convert back to RGB for Gradio
158
+ if restored_img is not None:
159
+ return restored_img[:, :, ::-1]
160
+
161
+ return image # Return original if processing failed
162
+
163
+ # Create Gradio interface
164
+ app = gr.Interface(
165
+ fn=process_image_gradio,
166
+ inputs=gr.Image(type="numpy"),
167
+ outputs=gr.Image(),
168
+ title="GFPGAN Face Restoration (CPU)",
169
+ description="Upload an image to improve facial details with GFPGAN running on CPU"
170
+ )
171
 
172
+ return app
173
 
174
+ # For command-line usage
175
  def main():
176
+ import argparse
177
+ import glob
178
+
179
  parser = argparse.ArgumentParser(description='GFPGAN for CPU')
180
  parser.add_argument('--input', type=str, default='inputs', help='Input image or folder')
181
  parser.add_argument('--output', type=str, default='results', help='Output folder')
 
200
 
201
  print(f'Results are saved in {output_dir}')
202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  if __name__ == '__main__':
 
 
204
  # Check if running in a Hugging Face Space
205
  if os.getenv('SPACE_ID'):
 
 
 
 
 
 
206
  app = create_gradio_app()
207
  app.launch()
208
  else: