import platform,sys,redis,time,requests,json,atexit sys.path.append('../libs/') import config,libs,libs_db_temp,common import os, sys, time, argparse, requests, json, re, oss2 import bpy import open3d as o3d import shutil import psutil # 下载 obj mtl jpg 文件 修正obj 的贴地板 及身高尺寸 生成预览图 #文件存储lua路径 diskName = "G:\\" filePath = "G://obj_fix/auto" #获取真实身高 def get_real_height(input_path): get_real_height_url = 'https://mp.api.suwa3d.com/api/physical/infoByPid' print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: Getting real height from {input_path}') pid = re.findall(r'(\d+)', input_path)[0] print(f'pid: {pid}') res = requests.get(get_real_height_url, params={'pid': pid}) res = json.loads(res.text) if res['code'] == -1: print(f'Error: {res["message"]}, return default height 160') return 160 height = res['data']['height'] if height == 0: print(f'Error: height=0, return default height 160') return 160 print(f'height: {height}') return height def base_fix(input_path): if not os.path.exists(input_path): print(f'Error: {input_path} does not exist.') return "error" bpy.ops.wm.read_homefile() bpy.ops.object.delete(use_global=False, confirm=False) bpy.ops.wm.obj_import(filepath=input_path) bpy.context.scene.unit_settings.scale_length = 1 bpy.context.scene.unit_settings.length_unit = 'CENTIMETERS' bpy.context.scene.unit_settings.mass_unit = 'GRAMS' obj = bpy.context.selected_objects[0] bpy.context.view_layer.objects.active = obj obj.select_set(True) # 脚底贴地 bpy.ops.object.align(align_mode='OPT_1', relative_to='OPT_1', align_axis={'Z'}) bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) real_height = get_real_height(input_path) print(obj.dimensions) scale = real_height / obj.dimensions[2] / 100 # 除以100是因为单位是厘米 bpy.context.object.scale = (scale, scale, scale) bpy.context.object.rotation_euler = (0, 0, 0) bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_VOLUME', center='MEDIAN') bpy.context.object.location[0] = 0 # 移动到特定位置(1m, 1m)是为了让human3d可以正确识别 bpy.context.object.location[1] = 0 bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) # # bpy.ops.wm.save_mainfile(filepath=args.input_path.replace('.obj', '.blend')) # output_file = input_path.replace('.obj', 'test.obj') bpy.ops.wm.obj_export(filepath=input_path.replace('.obj', '_base_fix.obj')) return obj #检测mtl文件最后一行是否 map_Kd 7126Tex1.jpg def check_mtl(tempMtlFilePath,pid): start_time = time.time() print(f"{pid}-开始检测mtl文件-开始时间-{start_time}") #读取mtl文件 if not os.path.exists(tempMtlFilePath): return False with open(tempMtlFilePath, 'r', encoding='utf-8') as f: lines = f.readlines() if len(lines) > 0: line = lines[-1] print(line) if "map_Kd" in line and f"{pid}Tex1.jpg" in line: print(f"{pid}-检测mtl文件-成功-耗时-{time.time()-start_time}") return True else: #删除最后一行 if "map_Kd" in line and f"{pid}.jpg" in line: lines.pop() #最后一行插入 map_Kd 7126Tex1.jpg lines.append(f"map_Kd {pid}Tex1.jpg\n") with open(tempMtlFilePath, 'w', encoding='utf-8') as f: f.writelines(lines) print(f"{pid}-检测mtl文件-成功-耗时-{time.time()-start_time}") return True print(f"{pid}-检测mtl文件-失败-耗时-{time.time()-start_time}") return False #生成预览图 def create_preview(obj_file_path,image_save_path,pid): start_time = time.time() print(f"{pid}-开始生成预览图-开始时间-{start_time}") # 加载 OBJ 文件 mesh = o3d.io.read_triangle_mesh(obj_file_path,enable_post_processing=True) mesh.compute_vertex_normals() # 创建视觉化窗口 # o3d.visualization.MeshColorOption = o3d.visualization.MeshColorOption.Default vis = o3d.visualization.Visualizer() # render = o3d.visualization.RenderOption() width = 800 height = 600 vis.create_window(width=width, height=height,visible=False) # 添加几何体到视觉化窗口 vis.add_geometry(mesh) vis.get_render_option().light_on = True # vis.get_render_option().mesh_color_option = o3d.visualization.MeshColorOption.Default vis.get_render_option().mesh_shade_option = o3d.visualization.MeshShadeOption.Default # render.background_color = [123,251,89] # 将光照强度设置为0.5或更低 # vis.get_render_option().ambient_intensity = 0.9 # 设置环境光强度 # vis.get_render_option().directional_light = False # 关闭定向光 # vis.get_render_option().line_width = 2.0 # 更新渲染器并捕获屏幕图像 vis.update_renderer() vis.poll_events() vis.capture_screen_image(image_save_path) # 关闭窗口 vis.destroy_window() print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: {pid} Run time: ', time.time() - start_time) time.sleep(2) # 检测图片是否存在 if not os.path.exists(image_save_path): print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: {pid} Error: {image_save_path} does not exist.') return False #判断文件夹是否存在 if not os.path.exists(f"{filePath}/preview/"): os.makedirs(f"{filePath}/preview/") #图片存在则复制到指定的文件夹中 shutil.copy(image_save_path, f"{filePath}/preview/") return True #检测硬盘容量 def check_disk(): # 获取硬盘分区列表 partitions = psutil.disk_partitions() for partition in partitions: print("分区信息",partition) # 获取指定分区(比如'C:')的使用情况 if partition.mountpoint == diskName: # 更改为您要检测的硬盘分区 usage = psutil.disk_usage(partition.mountpoint) free = f'{usage.free / (1024**3):.2f}' free = float(free) print(f"{diskName}剩余容量{free}") if free < 3: print("硬盘空间不足") return False # print(f"Total: {usage.total / (1024**3):.2f} GB") # print(f"Used: {usage.used / (1024**3):.2f} GB") # print(f"Free: {usage.free / (1024**3):.2f} GB") # print(f"Percentage: {usage.percent}%") return True # def traverse_directory(directory): # for root, dirs, files in os.walk(directory): # print(f"当前目录: {root}") # print("子目录: ", dirs) # print("文件: ", files) # print() def readTask(): #遍历 G:\obj_fix\print\wrong folder_path = 'G:\\obj_fix\print\wrong' arrFiles = [] for root, dirs, files in os.walk(folder_path): # print(f"当前目录: {root}") # print("子目录: ", dirs) arrFiles = files # print("文件: ", files) # print() for file in arrFiles: if file.endswith('_ok.png'): #提取pid pid = file.split('_')[0] print(pid) base_fix(f'{filePath}/{pid}/{pid}_new.obj') return #读取数据库的任务 pid="164" base_fix(f'{filePath}/{pid}/{pid}_new.obj') #生成预览图 #res = create_preview(f'{filePath}/{pid}/{pid}_new.obj',f'{filePath}/{pid}/{pid}_preview.png',pid) return startTimeTask = time.time() pid = libs_db_temp.get_task_by_level() pid = str(pid) if pid == "": print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: 无任务,延时10s') time.sleep(10) return if int(pid) == 0: print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: 无任务,延时10s') time.sleep(10) return #记录状态为处理中 libs_db_temp.update_fix_status(pid,1) # #判断对应的文件夹是否存在,存在则删除 # if os.path.exists(f'{filePath}/{pid}'): # shutil.rmtree(f'{filePath}/{pid}') # #下载pid的对应的oss端的文件 # tempName = libs.down_obj_from_oss_for_fix(filePath, pid, "print") # if tempName == "no_file": # #记录状态为异常 -3 文件不存在 # libs_db_temp.update_fix_status(pid,-3) # return "error" # if tempName == "error": # #记录状态为异常 -1 # libs_db_temp.update_fix_status(pid,-2) # return "error" # if tempName == "": # print("找不到对应的obj文件") # #记录状态为异常 -1 # libs_db_temp.update_fix_status(pid,-1) # return # #处理逻辑 # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+"-"+pid+"-开始执行任务") # try: # res=base_fix(f'{filePath}/{pid}/{pid}.obj') # if res == "error": # #记录状态为异常 -2 # libs_db_temp.update_fix_status(pid,-1) # return "error" # #记录状态为成功 2 # # libs_db_temp.update_fix_status(pid,2) # except Exception as e: # #状态异常 -2 # libs_db_temp.update_fix_status(pid,-1) # return "error" # #检测 mtl文件是否有map_Kd 7126Tex1.jpg # res = check_mtl(f'{filePath}/{pid}/{pid}.mtl',pid) # if res == False: # #记录状态为异常 -2 # libs_db_temp.update_fix_status(pid,-2) # return "error" # time.sleep(2) #生成预览图 res = create_preview(f'{filePath}/{pid}/{pid}.obj',f'{filePath}/{pid}/{pid}_preview.png',pid) if not res: #记录状态为异常 -2 libs_db_temp.update_fix_status(pid,-2) return "error" libs_db_temp.update_fix_status(pid,2) print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: {pid} -任务完美结束总耗时: ', time.time() - startTimeTask) return True #程序主入口 if __name__ == '__main__': #atexit.register(common.notify,"处理数据校准任务已经停止") pid="90864" base_fix(f'{filePath}/{pid}/{pid}.obj') # readTask() # while True: # pid = readTask() # res = check_disk() # if res == False: # print("硬盘空间不足,无法执行任务") # break