bergML1 mattiagatti commited on
Commit
ca55618
·
0 Parent(s):

Duplicate from mattiagatti/image2mesh

Browse files

Co-authored-by: Mattia Gatti <[email protected]>

Files changed (5) hide show
  1. .gitattributes +33 -0
  2. README.md +13 -0
  3. app.py +123 -0
  4. examples/bed.png +0 -0
  5. requirements.txt +7 -0
.gitattributes ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
11
+ *.model filter=lfs diff=lfs merge=lfs -text
12
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
13
+ *.npy filter=lfs diff=lfs merge=lfs -text
14
+ *.npz filter=lfs diff=lfs merge=lfs -text
15
+ *.onnx filter=lfs diff=lfs merge=lfs -text
16
+ *.ot filter=lfs diff=lfs merge=lfs -text
17
+ *.parquet filter=lfs diff=lfs merge=lfs -text
18
+ *.pb filter=lfs diff=lfs merge=lfs -text
19
+ *.pickle filter=lfs diff=lfs merge=lfs -text
20
+ *.pkl filter=lfs diff=lfs merge=lfs -text
21
+ *.pt filter=lfs diff=lfs merge=lfs -text
22
+ *.pth filter=lfs diff=lfs merge=lfs -text
23
+ *.rar filter=lfs diff=lfs merge=lfs -text
24
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
25
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
26
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
27
+ *.tflite filter=lfs diff=lfs merge=lfs -text
28
+ *.tgz filter=lfs diff=lfs merge=lfs -text
29
+ *.wasm filter=lfs diff=lfs merge=lfs -text
30
+ *.xz filter=lfs diff=lfs merge=lfs -text
31
+ *.zip filter=lfs diff=lfs merge=lfs -text
32
+ *.zst filter=lfs diff=lfs merge=lfs -text
33
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Image2mesh
3
+ emoji: 👁
4
+ colorFrom: green
5
+ colorTo: blue
6
+ sdk: gradio
7
+ sdk_version: 3.19.1
8
+ app_file: app.py
9
+ pinned: false
10
+ duplicated_from: mattiagatti/image2mesh
11
+ ---
12
+
13
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import matplotlib.pyplot as plt
3
+ import numpy as np
4
+ import open3d as o3d
5
+ import os
6
+ from PIL import Image
7
+ import tempfile
8
+ import torch
9
+ from transformers import GLPNImageProcessor, GLPNForDepthEstimation
10
+
11
+
12
+ def predict_depth(image):
13
+ feature_extractor = GLPNImageProcessor.from_pretrained("vinvino02/glpn-nyu")
14
+ model = GLPNForDepthEstimation.from_pretrained("vinvino02/glpn-nyu")
15
+
16
+ # load and resize the input image
17
+ new_height = 480 if image.height > 480 else image.height
18
+ new_height -= (new_height % 32)
19
+ new_width = int(new_height * image.width / image.height)
20
+ diff = new_width % 32
21
+ new_width = new_width - diff if diff < 16 else new_width + 32 - diff
22
+ new_size = (new_width, new_height)
23
+ image = image.resize(new_size)
24
+
25
+ # prepare image for the model
26
+ inputs = feature_extractor(images=image, return_tensors="pt")
27
+
28
+ # get the prediction from the model
29
+ with torch.no_grad():
30
+ outputs = model(**inputs)
31
+ predicted_depth = outputs.predicted_depth
32
+
33
+ output = predicted_depth.squeeze().cpu().numpy() * 1000.0
34
+
35
+ # remove borders
36
+ pad = 16
37
+ output = output[pad:-pad, pad:-pad]
38
+ image = image.crop((pad, pad, image.width - pad, image.height - pad))
39
+
40
+ return image, output
41
+
42
+
43
+ def generate_mesh(image, depth_image, quality):
44
+ width, height = image.size
45
+
46
+ # depth_image = (depth_map * 255 / np.max(depth_map)).astype('uint8')
47
+ image = np.array(image)
48
+
49
+ # create rgbd image
50
+ depth_o3d = o3d.geometry.Image(depth_image)
51
+ image_o3d = o3d.geometry.Image(image)
52
+ rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth(image_o3d, depth_o3d,
53
+ convert_rgb_to_intensity=False)
54
+
55
+ # camera settings
56
+ camera_intrinsic = o3d.camera.PinholeCameraIntrinsic()
57
+ camera_intrinsic.set_intrinsics(width, height, 500, 500, width / 2, height / 2)
58
+
59
+ # create point cloud
60
+ pcd = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image, camera_intrinsic)
61
+
62
+ # outliers removal
63
+ cl, ind = pcd.remove_statistical_outlier(nb_neighbors=20, std_ratio=20.0)
64
+ pcd = pcd.select_by_index(ind)
65
+
66
+ # estimate normals
67
+ pcd.estimate_normals()
68
+ pcd.orient_normals_to_align_with_direction(orientation_reference=(0., 0., -1.))
69
+
70
+ # surface reconstruction
71
+ mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd, depth=quality, n_threads=1)[0]
72
+
73
+ # rotate the mesh
74
+ rotation = mesh.get_rotation_matrix_from_xyz((np.pi, np.pi, 0))
75
+ mesh.rotate(rotation, center=(0, 0, 0))
76
+
77
+ # save the mesh
78
+ temp_name = next(tempfile._get_candidate_names()) + '.obj'
79
+ o3d.io.write_triangle_mesh(temp_name, mesh)
80
+
81
+ return temp_name
82
+
83
+
84
+ def predict(image, quality):
85
+ image, depth_map = predict_depth(image)
86
+ depth_image = (depth_map * 255 / np.max(depth_map)).astype('uint8')
87
+ mesh_path = generate_mesh(image, depth_image, quality + 5)
88
+ colormap = plt.get_cmap('plasma')
89
+ depth_image = (colormap(depth_image) * 255).astype('uint8')
90
+ depth_image = Image.fromarray(depth_image)
91
+
92
+ return depth_image, mesh_path
93
+
94
+
95
+ # GUI
96
+ title = 'Image2Mesh'
97
+ description = 'Demo based on my <a href="https://towardsdatascience.com/generate-a-3d-mesh-from-an-image-with-python' \
98
+ '-12210c73e5cc">article</a>. This demo predicts the depth of an image and then generates the 3D mesh. ' \
99
+ 'Choosing a higher quality increases the time to generate the mesh. You can download the mesh by ' \
100
+ 'clicking the top-right button on the 3D viewer. '
101
+ examples = [[f'examples/{name}', 3] for name in sorted(os.listdir('examples'))]
102
+
103
+ # example image source:
104
+ # N. Silberman, D. Hoiem, P. Kohli, and Rob Fergus,
105
+ # Indoor Segmentation and Support Inference from RGBD Images (2012)
106
+
107
+ iface = gr.Interface(
108
+ fn=predict,
109
+ inputs=[
110
+ gr.Image(type='pil', label='Input Image'),
111
+ gr.Slider(1, 5, step=1, value=3, label='Mesh quality')
112
+ ],
113
+ outputs=[
114
+ gr.Image(label='Depth'),
115
+ gr.Model3D(label='3D Model', clear_color=[0.0, 0.0, 0.0, 0.0])
116
+ ],
117
+ examples=examples,
118
+ allow_flagging='never',
119
+ cache_examples=False,
120
+ title=title,
121
+ description=description
122
+ )
123
+ iface.launch()
examples/bed.png ADDED
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ gradio
2
+ matplotlib
3
+ numpy
4
+ open3d
5
+ Pillow
6
+ torch
7
+ transformers