Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -259,7 +259,7 @@ def enhance_depth_map(depth_map, detail_level='medium'):
|
|
259 |
|
260 |
# Convert depth map to 3D mesh with significantly enhanced detail
|
261 |
def depth_to_mesh(depth_map, image, resolution=100, detail_level='medium'):
|
262 |
-
"""Convert depth map to 3D mesh with highly improved detail preservation
|
263 |
# First, enhance the depth map for better details
|
264 |
enhanced_depth = enhance_depth_map(depth_map, detail_level)
|
265 |
|
@@ -314,38 +314,7 @@ def depth_to_mesh(depth_map, image, resolution=100, detail_level='medium'):
|
|
314 |
# Create vertices
|
315 |
vertices = np.vstack([x_grid.flatten(), -y_grid.flatten(), -z_values.flatten()]).T
|
316 |
|
317 |
-
# Create
|
318 |
-
# This will be used to filter out faces that contain transparent pixels
|
319 |
-
has_alpha = False
|
320 |
-
alpha_mask = np.ones((resolution, resolution), dtype=bool)
|
321 |
-
|
322 |
-
if image is not None:
|
323 |
-
if isinstance(image, Image.Image):
|
324 |
-
if image.mode == 'RGBA':
|
325 |
-
has_alpha = True
|
326 |
-
# Convert image to numpy array with alpha channel
|
327 |
-
img_array = np.array(image)
|
328 |
-
# Extract alpha channel
|
329 |
-
alpha_channel = img_array[:, :, 3]
|
330 |
-
|
331 |
-
# Create alpha mask by sampling alpha channel at grid positions
|
332 |
-
for i in range(resolution):
|
333 |
-
for j in range(resolution):
|
334 |
-
img_y = int(i * (img_array.shape[0] - 1) / (resolution - 1))
|
335 |
-
img_x = int(j * (img_array.shape[1] - 1) / (resolution - 1))
|
336 |
-
alpha_mask[i, j] = alpha_channel[img_y, img_x] > 10 # Threshold for transparency
|
337 |
-
elif isinstance(image, np.ndarray) and image.shape[2] == 4: # RGBA numpy array
|
338 |
-
has_alpha = True
|
339 |
-
alpha_channel = image[:, :, 3]
|
340 |
-
|
341 |
-
# Sample alpha channel at grid positions
|
342 |
-
for i in range(resolution):
|
343 |
-
for j in range(resolution):
|
344 |
-
img_y = int(i * (image.shape[0] - 1) / (resolution - 1))
|
345 |
-
img_x = int(j * (image.shape[1] - 1) / (resolution - 1))
|
346 |
-
alpha_mask[i, j] = alpha_channel[img_y, img_x] > 10 # Threshold for transparency
|
347 |
-
|
348 |
-
# Create faces (triangles) with transparency handling
|
349 |
faces = []
|
350 |
for i in range(resolution-1):
|
351 |
for j in range(resolution-1):
|
@@ -354,31 +323,25 @@ def depth_to_mesh(depth_map, image, resolution=100, detail_level='medium'):
|
|
354 |
p3 = (i + 1) * resolution + j
|
355 |
p4 = (i + 1) * resolution + (j + 1)
|
356 |
|
357 |
-
#
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
# Alternative triangulation for smoother surface
|
377 |
-
faces.append([p1, p2, p3])
|
378 |
-
faces.append([p2, p4, p3])
|
379 |
-
|
380 |
-
if len(faces) == 0:
|
381 |
-
raise ValueError("No faces generated - image may be completely transparent")
|
382 |
|
383 |
faces = np.array(faces)
|
384 |
|
@@ -393,11 +356,10 @@ def depth_to_mesh(depth_map, image, resolution=100, detail_level='medium'):
|
|
393 |
else:
|
394 |
img_array = image
|
395 |
|
396 |
-
# Create vertex colors with improved sampling
|
397 |
if resolution <= img_array.shape[0] and resolution <= img_array.shape[1]:
|
398 |
# Create vertex colors by sampling the image with bilinear interpolation
|
399 |
vertex_colors = np.zeros((vertices.shape[0], 4), dtype=np.uint8)
|
400 |
-
vertex_colors[:, 3] = 255 # Default alpha to opaque
|
401 |
|
402 |
# Get normalized coordinates for sampling
|
403 |
for i in range(resolution):
|
@@ -416,26 +378,23 @@ def depth_to_mesh(depth_map, image, resolution=100, detail_level='medium'):
|
|
416 |
|
417 |
vertex_idx = i * resolution + j
|
418 |
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
vertex_colors[vertex_idx, :3] = [r, g, b]
|
438 |
-
vertex_colors[vertex_idx, 3] = 255 # Full opacity for RGB images
|
439 |
else:
|
440 |
# Handle grayscale with bilinear interpolation
|
441 |
gray = int((1-wx)*(1-wy)*img_array[y0, x0] + wx*(1-wy)*img_array[y0, x1] +
|
@@ -455,9 +414,6 @@ def depth_to_mesh(depth_map, image, resolution=100, detail_level='medium'):
|
|
455 |
mesh.fix_normals()
|
456 |
|
457 |
return mesh
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
|
462 |
@app.route('/health', methods=['GET'])
|
463 |
def health_check():
|
|
|
259 |
|
260 |
# Convert depth map to 3D mesh with significantly enhanced detail
|
261 |
def depth_to_mesh(depth_map, image, resolution=100, detail_level='medium'):
|
262 |
+
"""Convert depth map to 3D mesh with highly improved detail preservation"""
|
263 |
# First, enhance the depth map for better details
|
264 |
enhanced_depth = enhance_depth_map(depth_map, detail_level)
|
265 |
|
|
|
314 |
# Create vertices
|
315 |
vertices = np.vstack([x_grid.flatten(), -y_grid.flatten(), -z_values.flatten()]).T
|
316 |
|
317 |
+
# Create faces (triangles) with optimized winding for better normals
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
318 |
faces = []
|
319 |
for i in range(resolution-1):
|
320 |
for j in range(resolution-1):
|
|
|
323 |
p3 = (i + 1) * resolution + j
|
324 |
p4 = (i + 1) * resolution + (j + 1)
|
325 |
|
326 |
+
# Calculate normals to ensure consistent orientation
|
327 |
+
v1 = vertices[p1]
|
328 |
+
v2 = vertices[p2]
|
329 |
+
v3 = vertices[p3]
|
330 |
+
v4 = vertices[p4]
|
331 |
+
|
332 |
+
# Calculate normals for both possible triangulations
|
333 |
+
# and choose the one that's more consistent
|
334 |
+
norm1 = np.cross(v2-v1, v4-v1)
|
335 |
+
norm2 = np.cross(v4-v3, v1-v3)
|
336 |
+
|
337 |
+
if np.dot(norm1, norm2) >= 0:
|
338 |
+
# Standard triangulation
|
339 |
+
faces.append([p1, p2, p4])
|
340 |
+
faces.append([p1, p4, p3])
|
341 |
+
else:
|
342 |
+
# Alternative triangulation for smoother surface
|
343 |
+
faces.append([p1, p2, p3])
|
344 |
+
faces.append([p2, p4, p3])
|
|
|
|
|
|
|
|
|
|
|
|
|
345 |
|
346 |
faces = np.array(faces)
|
347 |
|
|
|
356 |
else:
|
357 |
img_array = image
|
358 |
|
359 |
+
# Create vertex colors with improved sampling
|
360 |
if resolution <= img_array.shape[0] and resolution <= img_array.shape[1]:
|
361 |
# Create vertex colors by sampling the image with bilinear interpolation
|
362 |
vertex_colors = np.zeros((vertices.shape[0], 4), dtype=np.uint8)
|
|
|
363 |
|
364 |
# Get normalized coordinates for sampling
|
365 |
for i in range(resolution):
|
|
|
378 |
|
379 |
vertex_idx = i * resolution + j
|
380 |
|
381 |
+
if len(img_array.shape) == 3 and img_array.shape[2] == 3: # RGB
|
382 |
+
# Perform bilinear interpolation for each color channel
|
383 |
+
r = int((1-wx)*(1-wy)*img_array[y0, x0, 0] + wx*(1-wy)*img_array[y0, x1, 0] +
|
384 |
+
(1-wx)*wy*img_array[y1, x0, 0] + wx*wy*img_array[y1, x1, 0])
|
385 |
+
g = int((1-wx)*(1-wy)*img_array[y0, x0, 1] + wx*(1-wy)*img_array[y0, x1, 1] +
|
386 |
+
(1-wx)*wy*img_array[y1, x0, 1] + wx*wy*img_array[y1, x1, 1])
|
387 |
+
b = int((1-wx)*(1-wy)*img_array[y0, x0, 2] + wx*(1-wy)*img_array[y0, x1, 2] +
|
388 |
+
(1-wx)*wy*img_array[y1, x0, 2] + wx*wy*img_array[y1, x1, 2])
|
389 |
+
|
390 |
+
vertex_colors[vertex_idx, :3] = [r, g, b]
|
391 |
+
vertex_colors[vertex_idx, 3] = 255 # Alpha
|
392 |
+
elif len(img_array.shape) == 3 and img_array.shape[2] == 4: # RGBA
|
393 |
+
for c in range(4): # For each RGBA channel
|
394 |
+
vertex_colors[vertex_idx, c] = int((1-wx)*(1-wy)*img_array[y0, x0, c] +
|
395 |
+
wx*(1-wy)*img_array[y0, x1, c] +
|
396 |
+
(1-wx)*wy*img_array[y1, x0, c] +
|
397 |
+
wx*wy*img_array[y1, x1, c])
|
|
|
|
|
|
|
398 |
else:
|
399 |
# Handle grayscale with bilinear interpolation
|
400 |
gray = int((1-wx)*(1-wy)*img_array[y0, x0] + wx*(1-wy)*img_array[y0, x1] +
|
|
|
414 |
mesh.fix_normals()
|
415 |
|
416 |
return mesh
|
|
|
|
|
|
|
417 |
|
418 |
@app.route('/health', methods=['GET'])
|
419 |
def health_check():
|