39 KiB
39 KiB
In [ ]:
!nvidia-smiIn [ ]:
#@title Load library
TORCH_ENABLED = True
SCIPY_ENABLED = True
from transformers import pipeline
import requests
import numpy as np
from PIL import Image
from math import cos, sin
import math as m
import os
import cv2
import pandas as pd
import gc
try:
from scipy.spatial import cKDTree
except:
SCIPY_ENABLED = False
try:
import torch
except:
TORCH_ENABLED = FalseIn [ ]:
#@title Define functions
def clean():
for I in range(0,20):
gc.collect()
torch.cuda.empty_cache()
def export_PLY(points, name_file="model.ply", multiple_files=False, format_ascii="ascii"):
# Write PLY header
header = [
"ply",
f"format {(format_ascii)} 1.0",
f"element vertex {(points.shape[0])}",
"property float x",
"property float y",
"property float z",
"property uchar red",
"property uchar green",
"property uchar blue",
"end_header\n"
]
if not(name_file.endswith(".ply")):
name_file+=".ply"
if "ascii" in format_ascii:
header_cons = "\n".join(header)
if not(multiple_files):
with open(name_file, 'wb') as f:
np.savetxt(f, points, fmt='%g %g %g %d %d %d', header=header_cons, comments='')
with open(name_file, 'rb+') as fout:
fout.seek(-1, os.SEEK_END)
fout.truncate()
else:
def split_array(arr, n):
return [arr[i:i+n] for i in range(0, len(arr), n)]
for idx,points_ck in enumerate(split_array(points, 2097152)):
header = [
"ply",
f"format {(format_ascii)} 1.0",
f"element vertex {(points_ck.shape[0])}",
"property float x",
"property float y",
"property float z",
"property uchar red",
"property uchar green",
"property uchar blue",
"end_header\n"
]
name_file_t = name_file.split(".ply")[0]+"_"+str(idx)+".ply"
with open(name_file_t, 'wb') as f:
np.savetxt(f, points_ck, fmt='%g %g %g %d %d %d', header=header_cons, comments='')
with open(name_file_t, 'rb+') as fout:
fout.seek(-1, os.SEEK_END)
fout.truncate()
else:
xyz = points[:, :3].astype(np.float32)
rgb = points[:, 3:6].astype(np.uint8)
if (multiple_files):
def split_array(arr, n):
return [arr[i:i+n] for i in range(0, len(arr), n)]
xyz = split_array(xyz, 2097152)
rgb = split_array(rgb, 2097152)
else:
xyz =[xyz]
rgb =[rgb]
for idx,xyz_ in enumerate(xyz):
header = [
"ply",
f"format {(format_ascii)} 1.0",
f"element vertex {(xyz_.shape[0])}",
"property float x",
"property float y",
"property float z",
"property uchar red",
"property uchar green",
"property uchar blue",
"end_header"
]
structured_array = np.zeros(xyz_.shape[0], dtype=[
('x', '<f4'), # Little-endian float32
('y', '<f4'),
('z', '<f4'),
('red', 'u1'), # Unsigned byte (0-255)
('green', 'u1'),
('blue', 'u1')
])
rgb_ = rgb[idx]
name_file_t = (name_file.split(".ply")[0]+"_"+str(idx)+".ply" if multiple_files else name_file)
structured_array['x'] = xyz_[:, 0]
structured_array['y'] = xyz_[:, 1]
structured_array['z'] = xyz_[:, 2]
structured_array['red'] = rgb_[:, 0]
structured_array['green'] = rgb_[:, 1]
structured_array['blue'] = rgb_[:, 2]
with open(name_file_t, 'wb') as f:
f.write('\n'.join(header).encode('utf-8'))
f.write(b'\n') # Header ends with a newline
structured_array.tofile(f)
def from2Dto3D_vectorized(arrayDepth, arrayPixel, maxZ, quality=1):
# Check if the input shapes are compatible
assert arrayPixel.shape[:2] == arrayDepth.shape, "Pixel and Depth map shapes do not match"
W, H = arrayDepth.shape # Original dimensions
if quality > 1:
# Calculate new dimensions based on quality
new_W = (W - 1) * quality + 1
new_H = (H - 1) * quality + 1
# Generate new coordinates using linspace
new_X = np.linspace(0, W-1, new_W)
new_Y = np.linspace(0, H-1, new_H)
# Create meshgrid for new coordinates
xi, yi = np.meshgrid(new_X, new_Y, indexing='ij') # shapes (new_W, new_H)
# Prepare indices for interpolation
x0 = np.floor(xi).astype(int)
x1 = np.clip(x0 + 1, 0, W-1)
y0 = np.floor(yi).astype(int)
y1 = np.clip(y0 + 1, 0, H-1)
dx = xi - x0
dy = yi - y0
# Interpolate arrayDepth
tl = arrayDepth[x0, y0]
tr = arrayDepth[x0, y1]
bl = arrayDepth[x1, y0]
br = arrayDepth[x1, y1]
interpolated_depth = (
(1 - dx) * (1 - dy) * tl +
dx * (1 - dy) * tr +
(1 - dx) * dy * bl +
dx * dy * br
)
# Interpolate arrayPixel for each channel
interpolated_pixel = np.zeros((new_W, new_H, 3), dtype=arrayPixel.dtype)
for c in range(3):
tl_c = arrayPixel[x0, y0, c]
tr_c = arrayPixel[x0, y1, c]
bl_c = arrayPixel[x1, y0, c]
br_c = arrayPixel[x1, y1, c]
interpolated_c = (
(1 - dx) * (1 - dy) * tl_c +
dx * (1 - dy) * tr_c +
(1 - dx) * dy * bl_c +
dx * dy * br_c
)
interpolated_pixel[:, :, c] = interpolated_c.astype(arrayPixel.dtype)
# Update variables to use interpolated arrays
W, H = new_W, new_H
arrayDepth = interpolated_depth
arrayPixel = interpolated_pixel
# Use new_X and new_Y for coordinates
final_X, final_Y = np.meshgrid(new_X, new_Y, indexing='ij')
else:
# Original coordinates
x = np.arange(W)
y = np.arange(H)
final_X, final_Y = np.meshgrid(x, y, indexing='ij') # shapes (W, H)
# Calculate scaled Z values
d_min = np.min(arrayDepth)
d_max = np.max(arrayDepth)
if d_max - d_min > 1e-9:
Z = -(arrayDepth - d_min) / (d_max - d_min) * maxZ
else:
Z = np.zeros_like(arrayDepth, dtype=np.float64)
# Extract RGB components
R = arrayPixel[:, :, 0]
G = arrayPixel[:, :, 1]
B = arrayPixel[:, :, 2]
# Stack all components and reshape to Nx6
# Transpose to shape (H, W) for correct ordering when using 'ij' indexing
points = np.stack([
final_Y.T, final_X.T, Z.T,
R.T, G.T, B.T
], axis=-1)
points = points.reshape(-1, 6)
return points
def from2Dto3D_vectorized_torch(arrayDepth, arrayPixel, maxZ, quality=1):
# Ensure inputs are PyTorch tensors
assert isinstance(arrayDepth, torch.Tensor), "arrayDepth must be a torch.Tensor"
assert isinstance(arrayPixel, torch.Tensor), "arrayPixel must be a torch.Tensor"
# Check shape compatibility
assert arrayPixel.shape[:2] == arrayDepth.shape, "Pixel and Depth map shapes do not match"
W, H = arrayDepth.shape # Original dimensions
if quality > 1:
# Calculate new dimensions
new_W = (W - 1) * quality + 1
new_H = (H - 1) * quality + 1
# Generate coordinates (CHANGED: torch.linspace instead of np.linspace)
new_X = torch.linspace(0, W-1, new_W, device=arrayDepth.device)
new_Y = torch.linspace(0, H-1, new_H, device=arrayDepth.device)
# Create meshgrid (CHANGED: torch.meshgrid with indexing='ij')
xi, yi = torch.meshgrid(new_X, new_Y, indexing='ij')
# Prepare indices (CHANGED: torch.floor/int/clamp)
x0 = torch.floor(xi).long()
x1 = torch.clamp(x0 + 1, 0, W-1)
y0 = torch.floor(yi).long()
y1 = torch.clamp(y0 + 1, 0, H-1)
dx = xi - x0
dy = yi - y0
# Interpolate depth (CHANGED: Tensor indexing)
tl = arrayDepth[x0, y0]
tr = arrayDepth[x0, y1]
bl = arrayDepth[x1, y0]
br = arrayDepth[x1, y1]
interpolated_depth = (
(1 - dx) * (1 - dy) * tl +
dx * (1 - dy) * tr +
(1 - dx) * dy * bl +
dx * dy * br
)
# Interpolate pixel (CHANGED: Tensor operations preserve dtype)
interpolated_pixel = torch.zeros((new_W, new_H, 3),
dtype=arrayPixel.dtype,
device=arrayPixel.device)
for c in range(3):
tl_c = arrayPixel[x0, y0, c]
tr_c = arrayPixel[x0, y1, c]
bl_c = arrayPixel[x1, y0, c]
br_c = arrayPixel[x1, y1, c]
interpolated_c = (
(1 - dx) * (1 - dy) * tl_c +
dx * (1 - dy) * tr_c +
(1 - dx) * dy * bl_c +
dx * dy * br_c
)
interpolated_pixel[:, :, c] = interpolated_c.to(arrayPixel.dtype)
W, H = new_W, new_H
arrayDepth = interpolated_depth
arrayPixel = interpolated_pixel
final_X, final_Y = xi, yi
else:
# Original coordinates (CHANGED: torch.arange)
x = torch.arange(W, device=arrayDepth.device)
y = torch.arange(H, device=arrayDepth.device)
final_X, final_Y = torch.meshgrid(x, y, indexing='ij')
# Calculate Z (CHANGED: Tensor operations)
d_min = torch.min(arrayDepth)
d_max = torch.max(arrayDepth)
if (d_max - d_min).item() > 1e-9: # CHANGED: .item() for scalar comparison
Z = -(arrayDepth - d_min) / (d_max - d_min) * maxZ
else:
Z = torch.zeros_like(arrayDepth)
# Extract RGB (CHANGED: Tensor slicing)
R = arrayPixel[:, :, 0]
G = arrayPixel[:, :, 1]
B = arrayPixel[:, :, 2]
# Stack components (CHANGED: permute instead of transpose)
points = torch.stack([
final_Y.permute(1, 0), # Equivalent to .T in NumPy
final_X.permute(1, 0),
Z.permute(1, 0),
R.permute(1, 0),
G.permute(1, 0),
B.permute(1, 0)
], dim=-1)
return points.view(-1, 6) # CHANGED: view instead of reshape
def transform_points(points, translate=(0, 0, 0), rotate=(0, 0, 0), scale=(1,1,1)):
"""Apply 3D transformations to points (rotation first, then translation)"""
# Convert rotation angles to radians if needed (modify if using degrees)
rx, ry, rz = rotate
# Create rotation matrices
# X-axis rotation
rot_x = np.array([
[1, 0, 0],
[0, cos(rx), -sin(rx)],
[0, sin(rx), cos(rx)]
], dtype=np.float64)
# Y-axis rotation
rot_y = np.array([
[cos(ry), 0, sin(ry)],
[0, 1, 0],
[-sin(ry), 0, cos(ry)]
], dtype=np.float64)
# Z-axis rotation
rot_z = np.array([
[cos(rz), -sin(rz), 0],
[sin(rz), cos(rz), 0],
[0, 0, 1]
], dtype=np.float64)
# Combined rotation matrix (Z-Y-X order)
rotation_matrix = rot_z @ rot_y @ rot_x
points[:,0:3] = points[:,0:3].astype(np.float64)
points[:,0:3] = (points[:,0:3] * np.array(scale, dtype=np.float64)).astype(np.float64)
# Apply rotation
points[:,0:3] = (points[:,0:3] @ rotation_matrix.T).astype(np.float64)
# Apply translation
points[:,0:3] = (points[:,0:3] + np.array(translate, dtype=np.float64)).astype(np.float64)
return points
def project_points(points, fov=60, rotation=None, translation=None, scale=None, aspect_ratio=1, img_size=(1000,1000)):
"""Fast 3D->2D projection with perspective correction"""
if rotation is None:
rotation = np.zeros(3)
if translation is None:
translation = np.zeros(3)
if scale is None:
scale = np.ones(3)
# Calcolo parametri camera
fov_rad = m.radians(fov)
focal_length = img_size[1] / (2 * m.tan(fov_rad / 2)) # Focal length verticale
# Trasformazioni (camera guarda lungo -Z)
points = transform_points(points, translate=translation, rotate=rotation, scale=scale)
# Seleziona punti DAVANTI alla camera (z < 0)
valid = points[:, 2] < 0
points_t = points #[valid]
if len(points_t) == 0:
return np.empty((0, 2)), np.array([]), np.empty((0, 3))
# Calcolo coordinate proiettate
z = -points_t[:, 2] # Converti in distanza positiva
x_proj = (points_t[:, 0] * focal_length) / (z * aspect_ratio)
y_proj = (points_t[:, 1] * focal_length) / z
# Conversione a coordinate immagine (Y non invertito)
pixel_x = (x_proj + img_size[0]/2).astype(int)
pixel_y = (y_proj + img_size[1]/2).astype(int) # Rimosso il segno negativo
# Clip e normalizzazione
pixel_x = np.clip(pixel_x, 0, img_size[0]-1)
pixel_y = np.clip(pixel_y, 0, img_size[1]-1)
z_norm = (z - z.min()) / (z.max() - z.min())
return np.column_stack([pixel_x, pixel_y]), z_norm, points_t[:, 3:6]
def project_points_ortho(points, rotation=None, translation=None, scale=None):
"""Orthographic 3D->2D projection"""
if rotation is None:
rotation = np.zeros(3)
if translation is None:
translation = np.zeros(3)
if scale is None:
scale = np.ones(3)
# Apply transformations
points = transform_points(points, translate=translation, rotate=rotation, scale=scale)
# Orthographic projection
x_proj = points[:, 0] # Simple scaling + centering offset
y_proj = points[:, 1]
# Normalize depth (similar to perspective version)
z = points[:, 2]
z_min = z.min()
z_max = z.max()
z_range = z_max - z_min + 1e-5 # Avoid division by zero
z_norm = (z - z_min) / z_range
colors = points[:,3:6]
return np.column_stack([x_proj, y_proj]), z_norm, colors
def render_points_fast(points, rotation=None, translation=None, scale=None,
img_size=(1000, 1000), color=False, cameraType=0, fov=60, correction=False, ksize=(2,2), thresh=2):
"""Ultra-fast rendering using pure NumPy and PIL"""
# Project points to 2D
if cameraType==0:
proj, depth, colors = project_points_ortho(points, rotation=rotation, translation=translation)
else:
proj, depth, colors = project_points(points, fov=fov, aspect_ratio=img_size[1]/img_size[1], rotation=rotation, translation=translation, scale=scale, img_size=img_size)
if isinstance(proj, torch.Tensor):
proj=proj.detach().cpu().numpy()
depth=depth.detach().cpu().numpy()
colors=colors.detach().cpu().numpy()
# Convert to integer coordinates and filter valid points
proj = proj.astype(np.int32)
valid = (proj[:, 0] >= 0) & (proj[:, 0] < img_size[0]) & \
(proj[:, 1] >= 0) & (proj[:, 1] < img_size[1])
proj = proj[valid]
depth = depth[valid]
colors = colors[valid]
# Grayscale rendering based on depth
max_depth = depth.max() if depth.size > 0 else 1
min_depth = depth.min() if depth.size > 0 else 0
if max_depth - min_depth > 0:
depth_normalized = (depth - min_depth) / (max_depth - min_depth)
else:
depth_normalized = np.zeros_like(depth)
intensities = (255 - (depth_normalized * 255)).astype(np.uint16)
# Sort points by descending intensity to prioritize closer points
sorted_indices = np.argsort(-intensities)
proj_sorted = proj[sorted_indices]
y_coords = proj_sorted[:, 1]
x_coords = proj_sorted[:, 0]
df = pd.DataFrame({'y': y_coords, 'x': x_coords})
unique_indices = df.drop_duplicates().index.to_numpy()
# Extract unique coordinates and colors
unique_y = y_coords[unique_indices]
unique_x = x_coords[unique_indices]
if color:
# Extract colors from valid points (assuming points are Nx[x,y,z,r,g,b])
point_colors = colors.astype(np.uint16)
colors_sorted = point_colors[sorted_indices]
unique_colors = colors_sorted[unique_indices]
# Create color buffer and assign colors
color_buffer = np.ones((img_size[1], img_size[0], 3))
color_buffer = color_buffer*-1
color_buffer[unique_y, unique_x] = unique_colors
img = color_buffer
else:
point_colors = intensities
colors_sorted = point_colors[sorted_indices]
unique_colors = colors_sorted[unique_indices]
# Create color buffer and assign colors
color_buffer = np.ones((img_size[1], img_size[0]))
color_buffer = color_buffer*-1
color_buffer[unique_y, unique_x] = unique_colors
img = color_buffer
if correction:
point_colors = intensities
colors_sorted = point_colors[sorted_indices]
unique_colors = colors_sorted[unique_indices]
# Create color buffer and assign colors
depth_buffer = np.zeros((img_size[1], img_size[0]))
depth_buffer[unique_y, unique_x] = unique_colors
img_depth = depth_buffer
img = np.array(img)
img_dep = np.array(img_depth)
img_blur = blur_image_excluding_black(img, ksize, thresh)
#print(np.unique(img_blur))
mask = img_dep < thresh
(img[mask]) = (img_blur[mask])
img = img
return img
def clean_points(points, k, m):
points = np.asarray(points)
if points.size == 0:
return points.copy()
if k <= 0:
raise ValueError("k must be a positive integer")
n = len(points)
if k > n - 1:
return np.empty((0, points.shape[1]))
tree = cKDTree(points, balanced_tree=False)
# Query k+1 to include the point itself, then select the k-th neighbor
distances, _ = tree.query(points, k=k+1, workers=-1)
kth_distances = distances[:, k] # k-th neighbor after excluding self
mask = kth_distances <= m
return points[mask]
def interpolate_points(points, alpha=0.5, n_c=3):
"""
Interpolate three new points for each original point, positioned between the original and its three nearest neighbors.
Parameters:
points (numpy.ndarray): Input array of shape (N, 6) where each row is (x, y, z, r, g, b).
alpha (float): Interpolation factor (0.0 = original point, 1.0 = neighbor). Default is 0.5 (midpoint).
Returns:
numpy.ndarray: Array of interpolated points with shape (3*N, 6).
"""
# Extract coordinates and colors
coords = points[:, :3]
colors = points[:, 3:]
N = coords.shape[0]
# Build KDTree for efficient neighbor lookup
tree = cKDTree(coords, balanced_tree=False)
# Query for 4 nearest neighbors (including self), then exclude self
_, indices = tree.query(coords, k=n_c+1, workers=-1)
neighbor_indices = indices[:, 1:(n_c+1)] # Shape (N, 3)
# Prepare indices for vectorized operations
original_indices = np.repeat(np.arange(N), n_c)
neighbors_flat = neighbor_indices.ravel()
# Gather original and neighbor data
original_coords = coords[original_indices]
neighbor_coords = coords[neighbors_flat]
original_colors = colors[original_indices]
neighbor_colors = colors[neighbors_flat]
# Interpolate coordinates and colors
interpolated_coords = (1 - alpha) * original_coords + alpha * neighbor_coords
interpolated_colors = (1 - alpha) * original_colors + alpha * neighbor_colors
# Combine into new points array
new_points = np.hstack((interpolated_coords, interpolated_colors))
combined_points = np.vstack((points, new_points))
return combined_points
def convolve2d_np(image, kernel, mode='same'):
# Flip the kernel for convolution
kernel = np.flipud(np.fliplr(kernel))
k_h, k_w = kernel.shape
i_h, i_w = image.shape
# Determine padding
if mode == 'same':
pad_top = (k_h - 1) // 2
pad_bottom = (k_h - 1) - pad_top
pad_left = (k_w - 1) // 2
pad_right = (k_w - 1) - pad_left
padded_image = np.pad(image, ((pad_top, pad_bottom), (pad_left, pad_right)), mode='constant')
elif mode == 'valid':
padded_image = image
elif mode == 'full':
padded_image = np.pad(image, ((k_h-1, k_h-1), (k_w-1, k_w-1)), mode='constant')
else:
raise ValueError("Mode must be 'same', 'valid', or 'full'")
# Generate sliding windows
windows = np.lib.stride_tricks.sliding_window_view(padded_image, (k_h, k_w))
# Perform convolution by summing element-wise multiplication
result = np.sum(windows * kernel.reshape(1, 1, k_h, k_w), axis=(-2, -1))
return result
def blur_image_excluding_black(image, kernel_size=(4,4), threshold=2):
# Create mask for non-black pixels (all channels zero)
if image.ndim == 3:
mask = np.any(image > threshold, axis=-1).astype(float)
else:
mask = (image > threshold).astype(float)
kernel = np.ones(kernel_size)
if image.ndim == 3:
blurred = np.ones_like(image)*-1
for c in range(image.shape[2]):
channel = image[:, :, c]
masked_channel = channel * mask
sum_matrix = convolve2d_np(masked_channel, kernel, mode='same')
count_matrix = convolve2d_np(mask, kernel, mode='same')
with np.errstate(divide='ignore', invalid='ignore'):
mean_matrix = sum_matrix / count_matrix
# Where count is zero, use original pixel if non-black, else 0
blurred_channel = np.where(count_matrix > 1, mean_matrix, -1)
blurred[:, :, c] = blurred_channel
else:
masked_image = image * mask
sum_matrix = convolve2d_np(masked_image, kernel, mode='same')
count_matrix = convolve2d_np(mask, kernel, mode='same')
with np.errstate(divide='ignore', invalid='ignore'):
mean_matrix = sum_matrix / count_matrix
blurred = np.where(count_matrix > 0, mean_matrix, masked_image)
return blurredIn [ ]:
from google.colab import files
import ipywidgets as widgets
from IPython.display import display
import PIL
from PIL import Image, ImageDraw, ImageFilter
#@title #Load image from upload file
loadImage = False
mask = Image.new('RGBA', (512, 512), (255, 255, 255))
initt = None
url = None
display("Load Image:")
Up = files.upload()
for k, v in Up.items():
initt=Image.open(k)
print(initt.size)In [ ]:
#@title Generate depth map
test =True #@param {"type":"boolean"}
# load pipe
pipe = pipeline(task="depth-estimation", model="depth-anything/Depth-Anything-V2-Large-hf")
# load image
if test:
url = 'https://raw.githubusercontent.com/chri002/ComfyUI_depthMapOperation/refs/heads/main/assets/start.jpg'
image = Image.open(requests.get(url, stream=True).raw)
image = image.resize((int(image.size[0]), int(image.size[1])))
print(image.size)
else:
image=initt.convert("RGB")
# inference
depth_img = pipe(image)["depth"]In [ ]:
#@title Generate Cloud Points
depth =512#@param {"type" : "number"}
quality=2 #@param {"type" : "integer"}
img = torch.from_numpy((np.array(image)))
depth_map = torch.from_numpy(np.array(depth_img))
points = (from2Dto3D_vectorized_torch(depth_map, img, depth, quality)).cpu().numpy()In [ ]:
#@title Clean Cloud Points
k = 20#@param {"type" : "integer"}
distance = 16#@param {"type" : "number"}
points = transform_points(points, translate=(0, 0, 0), rotate=(0, 0, 0), scale=(1,1,2))
points = (clean_points(points, k=k, m=distance))
points = transform_points(points, translate=(0, 0, 0), rotate=(0, 0, 0), scale=(1,1,0.5))In [ ]:
#@title Local Rotation
rx=0#@param {"type" : "number"}
ry=0#@param {"type" : "number"}
rz=0#@param {"type" : "number"}
mx, Mx, my, My, mz, Mz = points[:,0].min(), points[:,0].max(), points[:,1].min(), points[:,1].max(), points[:,2].min(), points[:,2].max()
tx = -(Mx+mx)/2
ty = -(My+my)/2
tz = -(Mz+mz)/2
points = transform_points(points, translate=(tx, ty, tz), rotate=(0, 0, 0), scale=(1,1,1))
points = transform_points(points, translate=(0, 0, 0), rotate=(rx/180*m.pi, ry/180*m.pi, rz/180*m.pi), scale=(1,1,1))
points = transform_points(points, translate=(-tx, -ty, -tz), rotate=(0, 0, 0), scale=(1,1,1))In [ ]:
#@title Translation
tx=0#@param {"type" : "number"}
ty=0#@param {"type" : "number"}
tz=0#@param {"type" : "number"}
points = transform_points(points, translate=(tx, ty, tz), rotate=(0, 0, 0), scale=(1,1,1))In [ ]:
#@title Scale
sx=1#@param {"type" : "number"}
sy=1#@param {"type" : "number"}
sz=1#@param {"type" : "number"}
points = transform_points(points, translate=(0,0,0), rotate=(0, 0, 0), scale=(sx,sy,sz))In [ ]:
#@title Points interpolation
interpolate = 3 #@param {"type":"number"}
points = (interpolate_points(points, alpha=0.5, n_c=interpolate))In [ ]:
#@title Generate image
import datetime
start = datetime.datetime.now()
tend = 0
width,height = image.size
translation = np.array([-width/2,-height/2,0])
scale = np.array([1,1,-1])
fov=45 #@param {"type" : "number"}
correction = True #@param{"type":"boolean"}
k_size =2 #@param{"type" : "number"}
points_cop = transform_points(points.copy(), translate=translation, scale=scale)
translation = np.array([0,0, -(height/m.sin(m.radians(fov)))])
points_cop = transform_points(points_cop, translate=translation)
end_img = (render_points_fast(points_cop, img_size=(width,height), color=True, cameraType=1, fov=fov, correction=correction, ksize=(k_size,k_size), thresh=3))
background = 125*np.ones((int(image.size[0]/20),int(image.size[1]/20),3))
background[1::2, ::2,:]=255
background[::2, 1::2,:]=255
background= cv2.resize(background, image.size, interpolation = cv2.INTER_NEAREST)
mask = end_img[:,:,0]==-1
end_img[mask] = background[mask]
mask = end_img[:,:,1]==-1
end_img[mask] = background[mask]
mask = end_img[:,:,2]==-1
end_img[mask] = background[mask]
tend=datetime.datetime.now()
delta=tend-start
print("vertices: ",points.shape[0],"\ntime: ",delta)
img_end = Image.fromarray(end_img.astype(np.uint8))
images = [image, img_end]
widths, heights = zip(*(i.size for i in images))
total_width = sum(widths)
max_height = max(heights)
new_im = Image.new('RGB', (total_width, max_height))
x_offset = 0
for im in images:
new_im.paste(im, (x_offset,0))
x_offset += im.size[0]
display(new_im)In [ ]:
#@title Show Image
img_endIn [ ]:
#@title Export PLY
export_PLY(points.detach().cpu().numpy(), name_file="model.ply", multiple_files=False, format_ascii="binary_little_endian")In [ ]:
#@title Clean memory
clean()