diff --git a/download_print.py b/download_print.py index 023fd26..6bbe8de 100644 --- a/download_print.py +++ b/download_print.py @@ -141,18 +141,19 @@ def upload_result(base_original_obj_dir, oss_config, batch_id): pass if __name__ == "__main__": - parser = argparse.ArgumentParser() - is_by_batch = False - batch_id = 10118 - if is_by_batch: - # 通过batch_id下载 - - """ + is_use_parser = False + 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 = 10118 + + is_by_batch = False + if is_by_batch: + # 通过batch_id下载 workdir = f"{print_data_dir}{batch_id}" @@ -164,12 +165,6 @@ if __name__ == "__main__": else: # 通过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}" json_name = batch_id diff --git a/general.py b/general.py index 03fb858..3b4745b 100644 --- a/general.py +++ b/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 read_mesh +import shutil + # -------------------------- 开始:运行 ---------------------------------- def is_run_local_data(): @@ -193,6 +195,28 @@ def get_blank_path(is_small_machine=False): else: 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,"复制成功") + # -------------------------- 结束:模型 ---------------------------------- # -------------------------- 开始:碰撞检测和越界 -------------------------- diff --git a/print_factory_type_setting_obj_run.py b/print_factory_type_setting_obj_run.py index 77b244e..58cf0cd 100644 --- a/print_factory_type_setting_obj_run.py +++ b/print_factory_type_setting_obj_run.py @@ -7,7 +7,6 @@ import argparse script_dir = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, script_dir) -from print_show_weight_max_obj import copy_obj_2x from point_cloud_layout import * from test_load_json import load_show_save 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 oss_config +from general import copy_obj_2x from general import need_upload_result -from general import get_blank_path 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 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 - batch_id = "1" + is_use_parser = False + 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 selected_mode="紧凑" # 标准 紧凑 output_format="JSON" # 模型 JSON diff --git a/print_show_weight_max_obj.py b/print_show_weight_max_obj.py deleted file mode 100644 index bb4e33a..0000000 --- a/print_show_weight_max_obj.py +++ /dev/null @@ -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) \ No newline at end of file diff --git a/test_load_json.py b/test_load_json.py index 0320742..037f690 100644 --- a/test_load_json.py +++ b/test_load_json.py @@ -528,13 +528,15 @@ def load_show_save(base_path, dict_origin, batch_id, is_show=False): # 主程序 if __name__ == "__main__": - - parser = argparse.ArgumentParser() - parser.add_argument("--batch_id", type=str, required=False, help="batch_id") - args = parser.parse_args() - - # batch_id = args.batch_id - batch_id = "9910032" + + is_use_parser = False + if is_use_parser: + parser = argparse.ArgumentParser() + parser.add_argument("--batch_id", type=str, required=False, help="batch_id") + args = parser.parse_args() + batch_id = args.batch_id + else: + batch_id = "9910032" base_path = f"{print_data_dir}{batch_id}/"