Files
2019-04-21 12:31:37 +09:00

159 lines
4.5 KiB
Python

from copy import deepcopy
from math import pi, ceil
import scipy.ndimage
from scipy.spatial import distance
import numpy as np
import matplotlib.pyplot as plt
import trimesh
from trimesh import voxel
def load_stl(stl_path):
return trimesh.load(stl_path)
def stl_to_arr(stl_mesh, pad=True):
arr = voxel.VoxelMesh(mesh=stl_mesh, pitch=1).matrix_solid
if pad:
max_edge_dist = get_max_bbox_edge(stl_mesh)
arr = center_constant_pad(arr, max_edge_dist)
return arr
def generate_label(stl_mesh):
random_angle = np.random.choice(np.arange(-30, 30), 3, replace=True)
stl_mesh_random_rotated = rotate_stl(
stl_mesh, random_angle, axes=(1, 1, 1))
label_3d_arr = stl_to_arr(stl_mesh_random_rotated)
label_2d_arr = project_3d_arr_to_2d_arr(label_3d_arr)
return label_3d_arr, label_2d_arr, random_angle
def get_max_bbox_edge(stl_mesh):
vertices = stl_mesh.bounding_box.vertices
edge_dists = distance.cdist(vertices, vertices, 'euclidean')
max_edge_dist = int(edge_dists.max()) # temporary disable
return 40
def center_constant_pad(arr, target_shape):
x, y, z = arr.shape
x_num_pad_left = (target_shape - x) // 2
x_num_pad_right = ceil((target_shape - x) / 2)
y_num_pad_left = (target_shape - y) // 2
y_num_pad_right = ceil((target_shape - y) / 2)
z_num_pad_left = (target_shape - z) // 2
z_num_pad_right = ceil((target_shape - z) / 2)
return np.pad(arr, ((x_num_pad_left, x_num_pad_right), (y_num_pad_left,
y_num_pad_right), (z_num_pad_left, z_num_pad_right)), 'constant')
def rotate_stl(stl_mesh, angles, axes=(1, 1, 1)):
stl_mesh_rotated = deepcopy(stl_mesh)
rads = [i * pi / 180 for i in angles]
x_rad, y_rad, z_rad = rads
axis_x, axis_y, axis_z = axes
if axis_x:
stl_mesh_rotated.apply_transform(
trimesh.transformations.rotation_matrix(x_rad,
(1, 0, 0)))
if axis_y:
stl_mesh_rotated.apply_transform(
trimesh.transformations.rotation_matrix(y_rad,
(0, 1, 0)))
if axis_z:
stl_mesh_rotated.apply_transform(
trimesh.transformations.rotation_matrix(z_rad,
(0, 0, 1)))
return stl_mesh_rotated
def load_3d_img(npy_path):
arr_3d = np.load(npy_path)
assert arr_3d.ndim == 3
return arr_3d
def rotate_3d_arr(arr, rotate=(0, 0, 0)):
x_angle, y_angle, z_angle = rotate
arr_x_rotated = scipy.ndimage.interpolation.rotate(
arr, x_angle, mode="nearest", axes=(1, 2), reshape=False
)
arr_y_rotated = scipy.ndimage.interpolation.rotate(
arr_x_rotated, y_angle, mode="nearest", axes=(0, 2), reshape=False
)
arr_z_rotated = scipy.ndimage.interpolation.rotate(
arr_y_rotated, z_angle, mode="nearest", axes=(0, 1), reshape=False
)
return arr_z_rotated
def project_3d_arr_to_2d_arr(arr_3d, axis=-1):
arr_2d = arr_3d.max(axis)
return arr_2d
def get_iou(pred_img, target_img):
union = (pred_img + target_img).sum()
num_pred_ones = (pred_img).sum()
num_target_ones = (target_img).sum()
intersection = num_pred_ones + num_target_ones - union
iou = intersection / num_target_ones
return iou
def plot_3d_arr(arr_3d):
fig = plt.figure()
ax = fig.gca(projection="3d")
ax.voxels(arr_3d, edgecolor="k")
plt.show()
def plot_2d_img(arr_2d):
plt.figure()
plt.imshow(arr_2d)
plt.show()
def plot_stl_mesh(stl_mesh):
stl_mesh.show()
def unnormalize_action(action):
return [i * 30 for i in action]
class ReplayBuffer(object):
def __init__(self, max_size=1e6):
self.storage = []
self.max_size = max_size
self.ptr = 0
def add(self, data):
if len(self.storage) == self.max_size:
self.storage[int(self.ptr)] = data
self.ptr = (self.ptr + 1) % self.max_size
else:
self.storage.append(data)
def sample(self, batch_size):
ind = np.random.randint(0, len(self.storage), size=batch_size)
x, y, u, r, d = [], [], [], [], []
for i in ind:
X, Y, U, R, D = self.storage[i]
x.append(np.array(X, copy=False))
y.append(np.array(Y, copy=False))
u.append(np.array(U, copy=False))
r.append(np.array(R, copy=False))
d.append(np.array(D, copy=False))
x = np.array(x).reshape(-1, 1, *X.shape)
y = np.array(y).reshape(-1, 1, *Y.shape)
u = np.array(u)
r = np.array(r).reshape(-1, 1)
d = np.array(d).reshape(-1, 1)
return x, y, u, r, d