mike23415 commited on
Commit
7b0508c
·
verified ·
1 Parent(s): cceb154

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +31 -125
app.py CHANGED
@@ -1,136 +1,42 @@
 
 
1
  import os
2
- import torch
3
- import gradio as gr
4
- import numpy as np
5
  from PIL import Image
6
- import tempfile
7
- from skimage import measure
8
- import trimesh
9
- import torch.nn.functional as F
10
- import torchvision.transforms as transforms
11
 
12
- # Check if CUDA is available, otherwise use CPU
13
- device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
14
- print(f"Using device: {device}")
15
 
16
- # Define a simple neural network to extract depth from images
17
- class SimpleDepthNet(torch.nn.Module):
18
- def __init__(self):
19
- super(SimpleDepthNet, self).__init__()
20
- self.conv1 = torch.nn.Conv2d(3, 32, kernel_size=3, padding=1)
21
- self.conv2 = torch.nn.Conv2d(32, 64, kernel_size=3, padding=1)
22
- self.conv3 = torch.nn.Conv2d(64, 128, kernel_size=3, padding=1)
23
- self.conv4 = torch.nn.Conv2d(128, 1, kernel_size=3, padding=1)
24
- self.pool = torch.nn.MaxPool2d(2, 2)
25
- self.upsample = torch.nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
26
-
27
- def forward(self, x):
28
- # Encoder
29
- x = F.relu(self.conv1(x))
30
- x = self.pool(x)
31
- x = F.relu(self.conv2(x))
32
- x = self.pool(x)
33
-
34
- # Decoder
35
- x = self.upsample(x)
36
- x = F.relu(self.conv3(x))
37
- x = self.upsample(x)
38
- x = torch.sigmoid(self.conv4(x))
39
- return x
40
 
41
- # Initialize the model
42
- model = SimpleDepthNet().to(device)
 
 
43
 
44
- # Define transformation for input images
45
- transform = transforms.Compose([
46
- transforms.Resize((256, 256)),
47
- transforms.ToTensor(),
48
- ])
49
 
50
- def image_to_3d(image):
51
- """
52
- Convert a single image to a 3D model using a simple depth extraction approach
53
- """
54
- if image is None:
55
- return None, "No image provided"
56
-
57
  try:
58
- # Preprocess image
59
- img_tensor = transform(image).unsqueeze(0).to(device)
60
-
61
- # Generate depth map
62
- with torch.no_grad():
63
- depth = model(img_tensor)[0, 0].cpu().numpy()
64
-
65
- # Convert depth map to 3D points
66
- h, w = depth.shape
67
- y, x = np.meshgrid(np.arange(h), np.arange(w), indexing='ij')
68
-
69
- # Normalize coordinates
70
- x = (x - w/2) / max(w, h)
71
- y = (y - h/2) / max(w, h)
72
- z = depth - 0.5 # Center around zero
73
-
74
- # Create point cloud
75
- points = np.stack([x.flatten(), y.flatten(), z.flatten()], axis=1)
76
-
77
- # Get colors from original image
78
- img_np = np.array(image.resize((w, h))) / 255.0
79
- colors = img_np.reshape(-1, 3)
80
-
81
- # Create a mesh from the point cloud (using marching cubes on the depth map)
82
- verts, faces, _, _ = measure.marching_cubes(depth, 0.5)
83
- mesh = trimesh.Trimesh(vertices=verts, faces=faces)
84
-
85
- # Save as OBJ
86
- with tempfile.NamedTemporaryFile(suffix='.obj', delete=False) as obj_file:
87
- obj_path = obj_file.name
88
- mesh.export(obj_path)
89
-
90
- # Also save as PLY for better compatibility with Unity
91
- with tempfile.NamedTemporaryFile(suffix='.ply', delete=False) as ply_file:
92
- ply_path = ply_file.name
93
- mesh.export(ply_path)
94
-
95
- return [obj_path, ply_path], "3D model generated successfully!"
96
- except Exception as e:
97
- return None, f"Error: {str(e)}"
98
 
99
- def process_image(image):
100
- try:
101
- if image is None:
102
- return None, None, "Please upload an image first."
103
-
104
- results, message = image_to_3d(image)
105
-
106
- if results:
107
- return results[0], results[1], message
108
- else:
109
- return None, None, message
110
- except Exception as e:
111
- return None, None, f"Error: {str(e)}"
112
 
113
- # Create Gradio interface
114
- with gr.Blocks(title="Simple Image to 3D Converter") as demo:
115
- gr.Markdown("# Simple Image to 3D Converter")
116
- gr.Markdown("Upload an image to convert it to a simple 3D model that you can use in Unity or other engines.")
117
-
118
- with gr.Row():
119
- with gr.Column(scale=1):
120
- input_image = gr.Image(type="pil", label="Input Image")
121
- submit_btn = gr.Button("Convert to 3D")
122
-
123
- with gr.Column(scale=1):
124
- obj_file = gr.File(label="OBJ File (for editing)")
125
- ply_file = gr.File(label="PLY File (for Unity)")
126
- output_message = gr.Textbox(label="Output Message")
127
-
128
- submit_btn.click(
129
- fn=process_image,
130
- inputs=[input_image],
131
- outputs=[obj_file, ply_file, output_message]
132
- )
133
 
134
- # Launch the app
135
- if __name__ == "__main__":
136
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
1
+ from flask import Flask, request, jsonify, send_file
2
+ from flask_cors import CORS
3
  import os
 
 
 
4
  from PIL import Image
5
+ import io
6
+ import torch
7
+ from gfpgan import GFPGANer
 
 
8
 
9
+ app = Flask(__name__)
10
+ CORS(app)
 
11
 
12
+ model = GFPGANer(
13
+ model_path='https://github.com/TencentARC/GFPGAN/releases/download/v1.3.4/GFPGANv1.3.pth',
14
+ upscale=2,
15
+ arch='clean',
16
+ channel_multiplier=2,
17
+ bg_upsampler=None,
18
+ device='cpu'
19
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
+ @app.route('/enhance', methods=['POST'])
22
+ def enhance():
23
+ if 'image' not in request.files:
24
+ return jsonify({'error': 'No image uploaded'}), 400
25
 
26
+ img_file = request.files['image']
27
+ img = Image.open(img_file.stream).convert('RGB')
 
 
 
28
 
 
 
 
 
 
 
 
29
  try:
30
+ _, _, restored_img = model.enhance(np.array(img), has_aligned=False, only_center_face=True, paste_back=True)
31
+ result_img = Image.fromarray(restored_img)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
+ img_io = io.BytesIO()
34
+ result_img.save(img_io, 'JPEG')
35
+ img_io.seek(0)
 
 
 
 
 
 
 
 
 
 
36
 
37
+ return send_file(img_io, mimetype='image/jpeg')
38
+ except Exception as e:
39
+ return jsonify({'error': str(e)}), 500
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
+ if __name__ == '__main__':
42
+ app.run(host='0.0.0.0', port=5000)