Browse Source

代码整理

main
hesuicong 2 weeks ago
parent
commit
4bb714a3ed
  1. 23
      download_print.py
  2. 24
      general.py
  3. 17
      print_factory_type_setting_obj_run.py
  4. 754
      print_show_weight_max_obj.py
  5. 14
      test_load_json.py

23
download_print.py

@ -141,18 +141,19 @@ def upload_result(base_original_obj_dir, oss_config, batch_id):
pass pass
if __name__ == "__main__": if __name__ == "__main__":
parser = argparse.ArgumentParser()
is_by_batch = False is_use_parser = False
batch_id = 10118 if is_use_parser:
if is_by_batch: parser = argparse.ArgumentParser()
# 通过batch_id下载
"""
parser.add_argument("--batch_id", type=str, required=True, help="batch_id") parser.add_argument("--batch_id", type=str, required=True, help="batch_id")
args = parser.parse_args() args = parser.parse_args()
batch_id = args.batch_id batch_id = args.batch_id
""" else:
batch_id = 10118
is_by_batch = False
if is_by_batch:
# 通过batch_id下载
workdir = f"{print_data_dir}{batch_id}" workdir = f"{print_data_dir}{batch_id}"
@ -164,12 +165,6 @@ if __name__ == "__main__":
else: else:
# 通过Json下载 # 通过Json下载
"""
parser.add_argument("--batch_id", type=str, required=True, help="batch_id")
args = parser.parse_args()
batch_id = args.batch_id
"""
workdir = f"{print_data_dir}{batch_id}" workdir = f"{print_data_dir}{batch_id}"
json_name = batch_id json_name = batch_id

24
general.py

@ -8,6 +8,8 @@ from compute_print_net_out import down_sample
from compute_print_net_out import voxel_size from compute_print_net_out import voxel_size
from compute_print_net_out import read_mesh from compute_print_net_out import read_mesh
import shutil
# -------------------------- 开始:运行 ---------------------------------- # -------------------------- 开始:运行 ----------------------------------
def is_run_local_data(): def is_run_local_data():
@ -193,6 +195,28 @@ def get_blank_path(is_small_machine=False):
else: else:
return os.path.join(print_factory_type_dir, "print_setting/blank/blank_big.obj") return os.path.join(print_factory_type_dir, "print_setting/blank/blank_big.obj")
def copy_obj_2x(base_obj_dir):
obj_list = [aa for aa in os.listdir(base_obj_dir) if aa.endswith(".obj")]
for obj_name in obj_list:
if "_F" in obj_name:
continue
obj_count = obj_name.split("x")[-1].replace(".obj","")
if not obj_count.isnumeric():
match = re.search(r"x(\d+)", obj_name)
if match:
obj_count = match.group(1)
else:
print("未找到 x 后的数字")
obj_count_num = int(obj_count)
if obj_count_num!=1:
for i in range(obj_count_num-1):
origin_path = os.path.join(base_obj_dir,obj_name)
dis_path = os.path.join(base_obj_dir,obj_name.replace(".obj",f"_F{i+1}.obj"))
if not os.path.exists(dis_path):
shutil.copy(origin_path,dis_path)
print(dis_path,"复制成功")
# -------------------------- 结束:模型 ---------------------------------- # -------------------------- 结束:模型 ----------------------------------
# -------------------------- 开始:碰撞检测和越界 -------------------------- # -------------------------- 开始:碰撞检测和越界 --------------------------

17
print_factory_type_setting_obj_run.py

@ -7,7 +7,6 @@ import argparse
script_dir = os.path.dirname(os.path.abspath(__file__)) script_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, script_dir) sys.path.insert(0, script_dir)
from print_show_weight_max_obj import copy_obj_2x
from point_cloud_layout import * from point_cloud_layout import *
from test_load_json import load_show_save from test_load_json import load_show_save
from download_print import upload_result from download_print import upload_result
@ -19,8 +18,8 @@ from config import big_machine_size
from config import small_machine_size from config import small_machine_size
from config import oss_config from config import oss_config
from general import copy_obj_2x
from general import need_upload_result from general import need_upload_result
from general import get_blank_path
from point_cloud_layout import make_bbox_for_print from point_cloud_layout import make_bbox_for_print
@ -180,12 +179,16 @@ def print_type_setting_obj(base_original_obj_dir=None,batch_id=0,selected_mode="
return 0 return 0
if __name__ == '__main__': if __name__ == '__main__':
# parser = argparse.ArgumentParser()
# parser.add_argument("--batch_id", type=str, required=True, help="batch_id")
# args = parser.parse_args()
# batch_id = args.batch_id is_use_parser = False
batch_id = "1" if is_use_parser:
parser = argparse.ArgumentParser()
parser.add_argument("--batch_id", type=str, required=True, help="batch_id")
args = parser.parse_args()
batch_id = args.batch_id
else:
batch_id = "1"
src_dir = batch_id src_dir = batch_id
selected_mode="紧凑" # 标准 紧凑 selected_mode="紧凑" # 标准 紧凑
output_format="JSON" # 模型 JSON output_format="JSON" # 模型 JSON

754
print_show_weight_max_obj.py

@ -1,754 +0,0 @@
import os.path
import shutil
import open3d as o3d
import numpy as np
import copy
from tqdm import tqdm
import time
import multiprocessing
import oss2
from joblib import Parallel, delayed
import itertools
from numba import njit, prange
#import bpy
from plyfile import PlyData, PlyElement
from multiprocessing import Pool, RawArray
import ctypes
import itertools
from compute_print_net_out import down_sample
def make_pcd_plane():
# 创建Y=0的平面点云
width = 60.0 # 平面的宽度
height = 60.0 # 平面的高度
resolution = 50 # 点云的分辨率,越高越密集
# 生成平面点云
x = np.linspace(-width / 2, width / 2, resolution)
y = np.linspace(-height / 2, height / 2, resolution)
xv, yv = np.meshgrid(x, y)
zv = np.zeros_like(xv) # Y 坐标恒为 0
# 将网格转换为点云的顶点数组
points_plane = np.vstack((xv.flatten(), yv.flatten(), zv.flatten())).T
# 创建Open3D点云对象
pcd_plane = o3d.geometry.PointCloud()
pcd_plane.points = o3d.utility.Vector3dVector(points_plane)
pcd_plane.paint_uniform_color([0, 1, 0])
return pcd_plane
def calculate_rotation_and_center_of_mass(angle_x, angle_y, angle_z, points):
"""计算某一组旋转角度后的重心"""
# 计算绕X轴、Y轴和Z轴的旋转矩阵
R_x = np.array([
[1, 0, 0],
[0, np.cos(np.radians(angle_x)), -np.sin(np.radians(angle_x))],
[0, np.sin(np.radians(angle_x)), np.cos(np.radians(angle_x))]
])
R_y = np.array([
[np.cos(np.radians(angle_y)), 0, np.sin(np.radians(angle_y))],
[0, 1, 0],
[-np.sin(np.radians(angle_y)), 0, np.cos(np.radians(angle_y))]
])
R_z = np.array([
[np.cos(np.radians(angle_z)), -np.sin(np.radians(angle_z)), 0],
[np.sin(np.radians(angle_z)), np.cos(np.radians(angle_z)), 0],
[0, 0, 1]
])
# 综合旋转矩阵
R = R_z @ R_y @ R_x
# 执行旋转
rotated_points = points @ R.T
# 计算最小z值
min_z = np.min(rotated_points[:, 2])
# 计算平移向量,将最小Z值平移到0
translation_vector = np.array([0, 0, -min_z])
rotated_points += translation_vector
# 计算重心
center_of_mass = np.mean(rotated_points, axis=0)
return center_of_mass[2], angle_x, angle_y, angle_z
#"""
@njit
def safe_min(arr):
if arr.size == 0:
return np.inf
return np.min(arr)
# 核心计算函数(支持Numba加速)
@njit(fastmath=True, cache=True)
def calculate_rotation_z(angle_x, angle_y, angle_z, points, cos_cache, sin_cache, angle_step):
#计算单个旋转组合后的重心Z坐标(无显式平移)
if points.shape[0] == 0:
return np.inf # 返回极大值避免干扰最优解
# 获取预计算的三角函数值
idx_x = angle_x // angle_step
idx_y = angle_y // angle_step
idx_z = angle_z // angle_step
cos_x = cos_cache[idx_x]
sin_x = sin_cache[idx_x]
cos_y = cos_cache[idx_y]
sin_y = sin_cache[idx_y]
cos_z = cos_cache[idx_z]
sin_z = sin_cache[idx_z]
# 构造旋转矩阵(展开矩阵乘法优化)
# R = Rz @ Ry @ Rx
# 计算矩阵元素(手动展开矩阵乘法)
m00 = cos_z * cos_y
m01 = cos_z * sin_y * sin_x - sin_z * cos_x
m02 = cos_z * sin_y * cos_x + sin_z * sin_x
m10 = sin_z * cos_y
m11 = sin_z * sin_y * sin_x + cos_z * cos_x
m12 = sin_z * sin_y * cos_x - cos_z * sin_x
m20 = -sin_y
m21 = cos_y * sin_x
m22 = cos_y * cos_x
# 计算所有点的Z坐标
z_values = np.empty(points.shape[0], dtype=np.float64)
for i in prange(points.shape[0]):
x, y, z = points[i, 0], points[i, 1], points[i, 2]
# 应用旋转矩阵
rotated_z = m20 * x + m21 * y + m22 * z
z_values[i] = rotated_z
# 计算重心Z(等效于平移后的重心)
# min_z = np.min(z_values)
min_z = safe_min(z_values)
avg_z = np.mean(z_values)
return avg_z - min_z # 等效于平移后的重心Z坐标
@njit(parallel=True, fastmath=True)
def _process_batch(batch, points, cos_cache, sin_cache, angle_step, results):
for i in prange(len(batch)):
ax, ay, az = batch[i]
results[i] = calculate_rotation_z(
ax, ay, az, points,
cos_cache, sin_cache, angle_step
)
def parallel_rotation2(points, angle_step=3):
#参数:
#points : numpy.ndarray (N,3) - 三维点云
#angle_step : int - 角度搜索步长(度数)
#返回:
#(best_angle_x, best_angle_y, best_angle_z, min_z)
points_np = np.asarray(points)
points_float64 = points_np.astype(np.float64)
points = np.ascontiguousarray(points_float64)
# points = np.ascontiguousarray(points.astype(np.float64))
# 生成所有可能角度
angles = np.arange(0, 360, angle_step)
n_angles = len(angles)
# 预计算三角函数值(大幅减少重复计算)
rads = np.radians(angles)
cos_cache = np.cos(rads).astype(np.float64)
sin_cache = np.sin(rads).astype(np.float64)
# 生成所有角度组合(内存优化版)
total_combinations = n_angles ** 3
# print(f"Total combinations: {total_combinations:,}")
# 分块处理以避免内存溢出
best_z = np.inf
best_angles = (0, 0, 0)
batch_size = 10 ** 6 # 根据可用内存调整
for x_chunk in range(0, n_angles, max(1, n_angles // 4)):
angles_x = angles[x_chunk:x_chunk + max(1, n_angles // 4)]
for y_chunk in range(0, n_angles, max(1, n_angles // 4)):
angles_y = angles[y_chunk:y_chunk + max(1, n_angles // 4)]
# 生成当前分块的所有组合
xx, yy, zz = np.meshgrid(angles_x, angles_y, angles)
current_batch = np.stack([xx.ravel(), yy.ravel(), zz.ravel()], axis=1)
# 处理子批次
for i in range(0, len(current_batch), batch_size):
batch = current_batch[i:i + batch_size]
results = np.zeros(len(batch), dtype=np.float64)
_process_batch(batch, points, cos_cache, sin_cache, angle_step, results)
# 更新最佳结果
min_idx = np.argmin(results)
if results[min_idx] < best_z:
best_z = results[min_idx]
best_angles = tuple(batch[min_idx])
# print(f"New best: {best_angles} -> Z={best_z:.4f}")
return (*best_angles, best_z)
#"""
#"""
def rotate_x(angle):
theta = np.radians(angle)
return np.array([
[1, 0, 0],
[0, np.cos(theta), -np.sin(theta)],
[0, np.sin(theta), np.cos(theta)]
])
def rotate_y(angle):
theta = np.radians(angle)
return np.array([
[np.cos(theta), 0, np.sin(theta)],
[0, 1, 0],
[-np.sin(theta), 0, np.cos(theta)]
])
def rotate_z(angle):
theta = np.radians(angle)
return np.array([
[np.cos(theta), -np.sin(theta), 0],
[np.sin(theta), np.cos(theta), 0],
[0, 0, 1]
])
def compute_z_height_and_center(rotated_points):
z_min, z_max = rotated_points[:, 2].min(), rotated_points[:, 2].max()
y_min, y_max = rotated_points[:, 1].min(), rotated_points[:, 1].max()
return (z_max - z_min), (y_min + y_max) / 2
def init_worker(shared_array, shape, dtype):
global global_points
global_points = np.frombuffer(shared_array, dtype=dtype).reshape(shape)
def compute_rotation(args):
angle_x, angle_y, angle_z = args
R = rotate_z(angle_z) @ rotate_y(angle_y) @ rotate_x(angle_x)
rotated_points = global_points @ R.T
z_height, center_y = compute_z_height_and_center(rotated_points)
return (angle_x, angle_y, angle_z, z_height, center_y)
def parallel_rotation3(points, angle_step=5):
# 生成所有旋转角度组合
angles = itertools.product(
np.arange(0, 360, angle_step),
np.arange(0, 360, angle_step),
np.arange(0, 360, angle_step)
)
# 共享内存初始化
shape, dtype = points.shape, points.dtype
shared_array = RawArray(ctypes.c_double, points.size)
shared_points = np.frombuffer(shared_array, dtype=dtype).reshape(shape)
np.copyto(shared_points, points)
# 多进程计算
with Pool(initializer=init_worker, initargs=(shared_array, shape, dtype)) as pool:
results = pool.imap_unordered(compute_rotation, angles, chunksize=100)
# 寻找最优解
best_angle = (0, 0, 0)
min_z_height = float('inf')
min_center_y = 0
for result in results:
if result[3] < min_z_height:
best_angle = result[:3]
min_z_height = result[3]
min_center_y = result[4]
return (*best_angle, min_center_y)
#"""
#"""
def parallel_rotation4(points, angle_step=4):
"""仅绕 Y 轴旋转(假设 X/Z 轴不影响目标函数)"""
min_center = float('inf')
best_angle = 0 # 遍历所有角度组合
"""
for angle_x in range(0, 360, angle_step):
for angle_y in range(0, 360, angle_step):
for angle_z in range(0, 360, angle_step):
center_of_mass_z, ax, ay, az = calculate_rotation_and_center_of_mass(
angle_x, angle_y, angle_z, points
)
if center_of_mass_z < min_center_of_mass_y:
min_center_of_mass_y = center_of_mass_z
best_angle_x, best_angle_y, best_angle_z = ax, ay, az
"""
#"""
for angle_x in range(-45, 45, angle_step):
for angle_y in range(0, 360, angle_step):
center_z, ax, ay, _ = calculate_rotation_and_center_of_mass(angle_x, angle_y, 0, points)
if center_z < min_center:
min_center = center_z
best_angle_x = ax
best_angle_y = ay
#"""
return (best_angle_x, best_angle_y, 0, min_center)
#"""
def compute_mesh_center(vertices):
"""
计算网格质心
参数:
vertices: 顶点坐标数组形状为(N, 3)的NumPy数组或列表
返回:
centroid: 质心坐标的NumPy数组 [x, y, z]
"""
if len(vertices) == 0:
raise ValueError("顶点数组不能为空")
n = len(vertices) # 顶点数量
# 初始化坐标累加器
sum_x, sum_y, sum_z = 0.0, 0.0, 0.0
# 遍历所有顶点累加坐标值
for vertex in vertices:
sum_x += vertex[0]
sum_y += vertex[1]
sum_z += vertex[2]
# 计算各坐标轴的平均值
centroid = np.array([sum_x / n, sum_y / n, sum_z / n])
return centroid
def get_lowest_position_of_center(obj_path,voxel_size,dict_origin,total_matrix):
mesh_obj = read_mesh(obj_path)
dict_origin[obj_path] = mesh_obj
# dict_origin[obj_path] = copy.deepcopy(mesh_obj)
#o3d.visualization.draw_geometries([mesh_obj])
vertices = np.asarray(mesh_obj.vertices)
# 确保网格有顶点
if len(vertices) == 0:
# raise ValueError(f"Mesh has no vertices: {obj_path}")
print(f"Warning: Mesh has no vertices: {obj_path}")
return None
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(vertices)
# o3d.visualization.draw_geometries([pcd])
# pcd = o3d.io.read_point_cloud(ply_file_path)
# print("voxel_size",voxel_size,obj_path, len(pcd.points), len(mesh_obj.vertices))
# 对点云进行下采样(体素网格法)
#"""
pcd_downsampled = down_sample(pcd, voxel_size)
pcd_downsampled.paint_uniform_color([0, 0, 1])
if len(np.asarray(pcd_downsampled.points)) <= 0:
bbox = pcd.get_axis_aligned_bounding_box()
volume = bbox.volume()
print(f"len(pcd.points)={len(pcd.points)}, volume={volume}")
# 处理体积为零的情况
if volume <= 0:
# 计算点云的实际范围
points = np.asarray(pcd.points)
if len(points) > 0:
min_bound = np.min(points, axis=0)
max_bound = np.max(points, axis=0)
extent = max_bound - min_bound
# 确保最小维度至少为0.01
min_dimension = max(0.01, np.min(extent))
volume = min_dimension ** 3
else:
volume = 1.0 # 最后的安全回退
print(f"Warning: Zero volume detected, using approximated volume {volume:.6f} for {obj_path}")
# 安全计算密度 - 防止除零错误
if len(pcd.points) > 0 and volume > 0:
original_density = len(pcd.points) / volume
voxel_size = max(0.01, min(10.0, 0.5 / (max(1e-6, original_density) ** 0.33)))
else:
# 当点数为0或体积为0时使用默认体素大小
voxel_size = 1.0 # 默认值
print(f"Recalculated voxel_size: {voxel_size} for {obj_path}")
pcd_downsampled = down_sample(pcd, voxel_size)
pcd_downsampled.paint_uniform_color([0, 0, 1])
#"""
original_num = len(pcd.points)
target_samples = 1000
num_samples = min(target_samples, original_num)
# 确保下采样后有点云
if len(np.asarray(pcd_downsampled.points)) == 0:
# 使用原始点云作为后备
pcd_downsampled = pcd
print(f"Warning: Using original point cloud for {obj_path} as downsampling produced no points")
points = np.asarray(pcd_downsampled.points)
# 初始化最小重心Y的值
min_center_of_mass_y = float('inf')
best_angle_x, best_angle_y, best_angle_z = 0, 0, 0
start_time = time.time()
# 旋转并计算最优角度:绕X、Y、Z轴进行每度的旋转
best_angle_x, best_angle_y, best_angle_z, min_center_of_mass_y = parallel_rotation4(points, angle_step=3)
print("get_lowest_position_of_center", obj_path, best_angle_x,best_angle_y,best_angle_z,"time",time.time()-start_time)
"""
# if best_angle_x >= 180:
if best_angle_x >= 155 and best_angle_x <= 325:
best_angle_x += 180
if best_angle_y >= 180:
best_angle_y += 180
if best_angle_z >= 180:
best_angle_z += 180
#"""
# 记录结束时间
end_time = time.time()
elapsed_time = end_time - start_time
# print(f"Time taken: {elapsed_time:.2f} seconds")
# 输出最佳的旋转角度
# print(f"Best Rotation Angles: angle_x = {best_angle_x}, angle_y = {best_angle_y}, angle_z = {best_angle_z}")
# print(f"Minimum Y Center of Mass: {min_center_of_mass_y}")
#time.sleep(1000)
# 使用最佳角度进行旋转并平移obj
pcd_transformed = copy.deepcopy(mesh_obj)
#"""
center = pcd_transformed.get_center()
#arrow = o3d.geometry.TriangleMesh.create_arrow(0.05, 0.1)
#arrow.translate(center)
#o3d.visualization.draw_geometries([pcd_transformed, arrow])
# 最佳角度旋转
R_x = pcd_transformed.get_rotation_matrix_from_axis_angle(np.array([1, 0, 0]) * np.radians(best_angle_x))
pcd_transformed.rotate(R_x)
R_y = pcd_transformed.get_rotation_matrix_from_axis_angle(np.array([0, 1, 0]) * np.radians(best_angle_y))
pcd_transformed.rotate(R_y)
R_z = pcd_transformed.get_rotation_matrix_from_axis_angle(np.array([0, 0, 1]) * np.radians(best_angle_z))
pcd_transformed.rotate(R_z)
# centroid = pcd.get_center()
centroid = pcd_transformed.get_center()
# z_mean1 = centroid[2]
T_x = np.eye(4)
T_x[:3, :3] = R_x
aabb = pcd_transformed.get_axis_aligned_bounding_box()
# center_point = aabb.get_center()
center_point = compute_mesh_center(mesh_obj.vertices)
T_center_to_origin = np.eye(4)
T_center_to_origin[:3, 3] = -center_point
T_origin_to_center = np.eye(4)
T_origin_to_center[:3, 3] = center_point
T_rot_center = T_origin_to_center @ T_x @ T_center_to_origin
total_matrix = T_rot_center @ total_matrix
T_y = np.eye(4)
T_y[:3, :3] = R_y
aabb = pcd_transformed.get_axis_aligned_bounding_box()
# center_point = aabb.get_center()
center_point = compute_mesh_center(mesh_obj.vertices)
T_center_to_origin = np.eye(4)
T_center_to_origin[:3, 3] = -center_point
T_origin_to_center = np.eye(4)
T_origin_to_center[:3, 3] = center_point
T_rot_center = T_origin_to_center @ T_y @ T_center_to_origin
total_matrix = T_rot_center @ total_matrix
T_z = np.eye(4)
T_z[:3, :3] = R_z
aabb = pcd_transformed.get_axis_aligned_bounding_box()
# center_point = aabb.get_center()
center_point = compute_mesh_center(mesh_obj.vertices)
T_center_to_origin = np.eye(4)
T_center_to_origin[:3, 3] = -center_point
T_origin_to_center = np.eye(4)
T_origin_to_center[:3, 3] = center_point
T_rot_center = T_origin_to_center @ T_z @ T_center_to_origin
total_matrix = T_rot_center @ total_matrix
#arrow = o3d.geometry.TriangleMesh.create_arrow(0.05, 0.1)
#arrow.translate(center)
#o3d.visualization.draw_geometries([pcd_transformed, arrow])
#"""
#"""
#试着旋转180,让脸朝上
#
vertices = np.asarray(pcd_transformed.vertices)
# 计算平移向量,将最小Y值平移到0
min_z = np.min(vertices[:, 2])
translation_vector = np.array([0,0,-min_z,])
pcd_transformed.translate(translation_vector)
T_trans1 = np.eye(4)
T_trans1[:3, 3] = translation_vector
total_matrix = T_trans1 @ total_matrix
#
# 计算 z 坐标均值
vertices = np.asarray(pcd_transformed.vertices)
z_mean1 = np.mean(vertices[:, 2])
angle_rad = np.pi
#print("旋转前质心:", pcd_transformed.get_center())
#print("旋转前点示例:", np.asarray(pcd_transformed.vertices)[:3])
R_y = pcd_transformed.get_rotation_matrix_from_axis_angle(np.array([0, 1, 0]) * angle_rad)
centroid = pcd_transformed.get_center()
pcd_transformed.translate(-center_point)
pcd_transformed.rotate(R_y, center=(0, 0, 0))
pcd_transformed.translate(center_point)
aabb = pcd_transformed.get_axis_aligned_bounding_box()
# center_point = aabb.get_center()
center_point = compute_mesh_center(mesh_obj.vertices)
# 构建绕中心点旋转的变换矩阵[3](@ref)
T_center_to_origin = np.eye(4)
T_center_to_origin[:3, 3] = -center_point
R_y180 = pcd_transformed.get_rotation_matrix_from_axis_angle(np.array([0, 1, 0]) * angle_rad)
T_rotate = np.eye(4)
T_rotate[:3, :3] = R_y180
T_origin_to_center = np.eye(4)
T_origin_to_center[:3, 3] = center_point
T_rot_center = T_origin_to_center @ T_rotate @ T_center_to_origin
total_matrix = T_rot_center @ total_matrix
#print("旋转后质心:", pcd_transformed.get_center())
#print("旋转后点示例:", np.asarray(pcd_transformed.vertices)[:3])
# centroid = pcd.get_center()
centroid = pcd_transformed.get_center()
# z_mean2 = centroid[2]
#
vertices = np.asarray(pcd_transformed.vertices)
# 计算平移向量,将最小Y值平移到0
min_z = np.min(vertices[:, 2])
max_z = np.max(vertices[:, 2])
# print("min_z1", min_z, obj_path)
translation_vector = np.array([0,0,-min_z,])
# translation_vector = np.array([0,0,-min_z + (min_z-max_z),])
# print("translation_vector1",translation_vector)
pcd_transformed.translate(translation_vector)
T_trans2 = np.eye(4)
T_trans2[:3, 3] = translation_vector
translation = total_matrix[:3, 3]
# print("translation_vector2",translation_vector)
# print(1,translation)
total_matrix = T_trans2 @ total_matrix
translation = total_matrix[:3, 3]
# print(2,translation)
# 计算 z 坐标均值
vertices = np.asarray(pcd_transformed.vertices)
z_mean2 = np.mean(vertices[:, 2])
# print("z_mean",z_mean1,z_mean2,len(pcd_transformed.vertices),obj_path)
if (z_mean2 > z_mean1):
R_y = pcd_transformed.get_rotation_matrix_from_axis_angle(np.array([0, 1, 0]) * -angle_rad)
centroid = pcd_transformed.get_center()
aabb = pcd_transformed.get_axis_aligned_bounding_box()
# center_point = aabb.get_center()
center_point = compute_mesh_center(mesh_obj.vertices)
pcd_transformed.translate(-center_point)
pcd_transformed.rotate(R_y, center=(0, 0, 0))
pcd_transformed.translate(center_point)
T_center_to_origin = np.eye(4)
T_center_to_origin[:3, 3] = -center_point
T_origin_to_center = np.eye(4)
T_origin_to_center[:3, 3] = center_point
# 构建反向旋转矩阵
R_y = pcd_transformed.get_rotation_matrix_from_axis_angle(np.array([0, 1, 0]) * -angle_rad)
T_rotate_inv = np.eye(4)
T_rotate_inv[:3, :3] = R_y
# 完整的反向绕中心旋转矩阵
T_rot_center_inv = T_origin_to_center @ T_rotate_inv @ T_center_to_origin
total_matrix = T_rot_center_inv @ total_matrix
#"""
vertices = np.asarray(pcd_transformed.vertices)
# 计算平移向量,将最小Y值平移到0
min_z = np.min(vertices[:, 2])
# print("min_z2", min_z, obj_path)
translation_vector = np.array([0,0,-min_z,])
pcd_transformed.translate(translation_vector)
T_trans3 = np.eye(4)
T_trans3[:3, 3] = translation_vector
total_matrix = T_trans3 @ total_matrix
translation = total_matrix[:3, 3]
# print(3,translation)
return pcd_transformed, total_matrix
def axis_angle_to_rotation_matrix(axis, angle):
"""手动生成旋转矩阵"""
axis = axis / np.linalg.norm(axis) # 单位化
cos_a = np.cos(angle)
sin_a = np.sin(angle)
return np.array([
[cos_a + axis[0]**2*(1-cos_a),
axis[0]*axis[1]*(1-cos_a) - axis[2]*sin_a,
axis[0]*axis[2]*(1-cos_a) + axis[1]*sin_a],
[axis[1]*axis[0]*(1-cos_a) + axis[2]*sin_a,
cos_a + axis[1]**2*(1-cos_a),
axis[1]*axis[2]*(1-cos_a) - axis[0]*sin_a],
[axis[2]*axis[0]*(1-cos_a) - axis[1]*sin_a,
axis[2]*axis[1]*(1-cos_a) + axis[0]*sin_a,
cos_a + axis[2]**2*(1-cos_a)]
])
def load_obj_data(get_pid,base_out_dir):
"""下载obj文件"""
access_key_id = os.getenv('OSS_TEST_ACCESS_KEY_ID', 'LTAI5tBWbfkZntfJij4Fg9gz')
access_key_secret = os.getenv('OSS_TEST_ACCESS_KEY_SECRET', 'sYDps1i9NSge6hn130EgpPJezKM6Gx')
bucket_name = os.getenv('OSS_TEST_BUCKET', 'suwa3d-securedata')
endpoint = os.getenv('OSS_TEST_ENDPOINT', 'https://oss-cn-shanghai.aliyuncs.com')
bucket = oss2.Bucket(oss2.Auth(access_key_id, access_key_secret), endpoint, bucket_name)
# if not os.path.exists(base_out_dir):
# os.makedirs(base_out_dir)
prefix = f"objs/print/{get_pid}/"
out_pid_dir = os.path.join(base_out_dir,str(get_pid))
for obj in oss2.ObjectIterator(bucket, prefix=prefix):
# 如果迭代器至少返回一个对象,那么表示该"文件夹"存在
if not os.path.exists(out_pid_dir):
os.makedirs(out_pid_dir)
#print("Folder exists.")
filename = obj.key[len(prefix):]
if get_pid not in filename:
continue
print("获取的文件名称",filename)
local_path = os.path.join(out_pid_dir, filename)
# 下载对象到本地文件
try:
bucket.get_object_to_file(obj.key, local_path)
print(f"Downloaded {obj.key} to {local_path}")
except:
print("下载错误",get_pid)
record_text = "./error_load.txt"
with open(record_text, 'a') as f:
f.write(get_pid + '\n')
else:
# 如果迭代器没有返回任何对象,那么表示该"文件夹"不存在
print("ossFolder does not exist.",get_pid)
import re
def copy_obj_2x(base_obj_dir):
obj_list = [aa for aa in os.listdir(base_obj_dir) if aa.endswith(".obj")]
for obj_name in obj_list:
if "_F" in obj_name:
continue
obj_count = obj_name.split("x")[-1].replace(".obj","")
if not obj_count.isnumeric():
match = re.search(r"x(\d+)", obj_name)
if match:
obj_count = match.group(1)
else:
print("未找到 x 后的数字")
obj_count_num = int(obj_count)
if obj_count_num!=1:
for i in range(obj_count_num-1):
origin_path = os.path.join(base_obj_dir,obj_name)
dis_path = os.path.join(base_obj_dir,obj_name.replace(".obj",f"_F{i+1}.obj"))
if not os.path.exists(dis_path):
shutil.copy(origin_path,dis_path)
print(dis_path,"复制成功")
def save_mesh_with_blender(obj_transformed, obj_path, apply_transform=True):
# o3d.io.write_triangle_mesh(obj_path, obj_transformed,write_triangle_uvs=True)
# return
"""使用 Blender 导出变换后的网格"""
# 创建新网格对象
mesh = bpy.data.meshes.new("TempMesh")
mesh.from_pydata(
np.asarray(obj_transformed.vertices),
[],
np.asarray(obj_transformed.triangles).tolist()
)
obj = bpy.data.objects.new("TempObject", mesh)
# 链接到场景
bpy.context.collection.objects.link(obj)
# 设置上下文
original_selection = bpy.context.selected_objects.copy()
original_active = bpy.context.view_layer.objects.active
bpy.ops.object.select_all(action='DESELECT')
obj.select_set(True)
bpy.context.view_layer.objects.active = obj
# 应用变换
if apply_transform:
bpy.ops.object.transform_apply(
location=True,
rotation=True,
scale=True
)
# 配置导出参数
export_settings = {
'filepath': obj_path,
'export_selected_objects': True,
'export_triangulated_mesh': True,
'forward_axis': 'Y',
'up_axis': 'Z',
'global_scale': 1.0
}
# 执行导出
try:
bpy.ops.wm.obj_export(**export_settings)
finally:
# 清理临时对象
bpy.data.objects.remove(obj, do_unlink=True)
bpy.data.meshes.remove(mesh)
# 恢复原始上下文
bpy.ops.object.select_all(action='DESELECT')
for o in original_selection:
o.select_set(True)
bpy.context.view_layer.objects.active = original_active
if __name__ == '__main__':
out_dir = "/data/datasets_20t/type_setting_test_data/"
base_out_dir = f"{out_dir}/8/"
weight_fix_out_dir = f"{out_dir}/print_weight_fix_data_obj"
weight_fix_out_ply_dir = f"{out_dir}/print_weight_fix_data_ply"
copy_obj_2x(base_out_dir)

14
test_load_json.py

@ -529,12 +529,14 @@ def load_show_save(base_path, dict_origin, batch_id, is_show=False):
# 主程序 # 主程序
if __name__ == "__main__": if __name__ == "__main__":
parser = argparse.ArgumentParser() is_use_parser = False
parser.add_argument("--batch_id", type=str, required=False, help="batch_id") if is_use_parser:
args = parser.parse_args() parser = argparse.ArgumentParser()
parser.add_argument("--batch_id", type=str, required=False, help="batch_id")
# batch_id = args.batch_id args = parser.parse_args()
batch_id = "9910032" batch_id = args.batch_id
else:
batch_id = "9910032"
base_path = f"{print_data_dir}{batch_id}/" base_path = f"{print_data_dir}{batch_id}/"

Loading…
Cancel
Save