OttoYu commited on
Commit
301a7b2
·
verified ·
1 Parent(s): a0c3f6a

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +109 -0
app.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import laspy
2
+ import numpy as np
3
+ import cv2
4
+ from math import floor, pi
5
+ from multiprocessing import Process, shared_memory, cpu_count
6
+ import gradio as gr
7
+ import time
8
+
9
+ # ==== Constants ====
10
+ TILE_DIM = 512
11
+ PRECISION = 16
12
+ FACTOR = 2 ** PRECISION
13
+ NUM_WORKERS = cpu_count()
14
+ SHARED_MEMORY_NAME = 'shared_canvas'
15
+
16
+ # ==== Parameters ====
17
+ IMAGE_HEIGHT = 4096 * 2
18
+ POINT_SIZE = 3
19
+ SCALE_COLORS = False
20
+ FULL_RES = False
21
+
22
+ def create_shared_memory_array(data, name, dtype):
23
+ shm = shared_memory.SharedMemory(create=True, size=data.nbytes, name=name)
24
+ shared_array = np.ndarray(data.shape, dtype=dtype, buffer=shm.buf)
25
+ shared_array[:] = data
26
+ return shm
27
+
28
+ def release_shared_memory(name):
29
+ shm = shared_memory.SharedMemory(name=name)
30
+ shm.close()
31
+ shm.unlink()
32
+
33
+ def draw_points(start, length, canvas_shape, theta, phi, radius, color):
34
+ shm = shared_memory.SharedMemory(name=SHARED_MEMORY_NAME)
35
+ canvas = np.ndarray(canvas_shape, dtype=np.uint16, buffer=shm.buf)
36
+
37
+ for i in range(start, start + length):
38
+ cv2.circle(
39
+ canvas,
40
+ (theta[i], phi[i]),
41
+ radius[i],
42
+ color=(int(color[i][0]), int(color[i][1]), int(color[i][2])),
43
+ thickness=cv2.FILLED,
44
+ shift=PRECISION
45
+ )
46
+
47
+ def project_point_cloud(input_file):
48
+ try:
49
+ point_cloud = laspy.read(input_file)
50
+ except FileNotFoundError:
51
+ return "Input file not found."
52
+
53
+ height, width = IMAGE_HEIGHT, IMAGE_HEIGHT * 2
54
+ output_shape = (height, width, 3)
55
+ total_points = point_cloud.header.point_count
56
+
57
+ background = np.zeros(output_shape, dtype=np.uint16)
58
+
59
+ xyz = np.array([point_cloud.x, point_cloud.y, point_cloud.z])
60
+ distances = np.linalg.norm(xyz, axis=0)
61
+ distances_norm = (distances - distances.min()) / (distances.max() - distances.min())
62
+
63
+ theta = ((width * FACTOR) -
64
+ (((np.arctan2(point_cloud.y, point_cloud.x) + pi) / (2 * pi)) * width * FACTOR)).astype(np.uint64)
65
+ phi = ((np.arccos(point_cloud.z / distances) / pi) * height * FACTOR).astype(np.uint64)
66
+ radii = (FACTOR * POINT_SIZE * (1 - distances_norm) + 1).astype(np.uint64)
67
+
68
+ colors = np.stack([point_cloud.blue, point_cloud.green, point_cloud.red], axis=-1).astype(np.uint16)
69
+ if SCALE_COLORS:
70
+ colors *= 256
71
+
72
+ shm_canvas = create_shared_memory_array(background, SHARED_MEMORY_NAME, np.uint16)
73
+
74
+ processes = []
75
+ num_threads = min(NUM_WORKERS, 4) # Limit to a reasonable number of threads
76
+ for i in range(num_threads):
77
+ start = floor(i * total_points / num_threads)
78
+ end = floor((i + 1) * total_points / num_threads)
79
+ p = Process(target=draw_points, args=(start, end - start, output_shape, theta, phi, radii, colors))
80
+ p.start()
81
+ processes.append(p)
82
+
83
+ for p in processes:
84
+ p.join()
85
+
86
+ final_image = np.ndarray(output_shape, dtype=np.uint16, buffer=shm_canvas.buf)
87
+ if not FULL_RES:
88
+ final_image = (final_image / 256).astype(np.uint8)
89
+
90
+ output_file = "output_image.jpg"
91
+ cv2.imwrite(output_file, final_image)
92
+
93
+ release_shared_memory(SHARED_MEMORY_NAME)
94
+ return output_file
95
+
96
+ # Gradio interface
97
+ def main(input_file):
98
+ return project_point_cloud(input_file)
99
+
100
+ iface = gr.Interface(
101
+ fn=main,
102
+ inputs=gr.inputs.File(label="Upload LAS File"),
103
+ outputs=gr.outputs.Image(type="file", label="Output Image"),
104
+ title="Point Cloud Projection",
105
+ description="Upload a LAS file to project the point cloud into an image."
106
+ )
107
+
108
+ if __name__ == "__main__":
109
+ iface.launch()