Browse Source

同步更改数据

master
dongchangxi 1 year ago
parent
commit
33ba8bb357
  1. 1
      .gitignore
  2. 30
      libs/config.py
  3. 24
      libs/libs.py
  4. 213
      libs/libs_db_temp.py
  5. 273
      script/bacth_obj_bake_vertex_high_ply.py
  6. 296
      script/base_data_fix.py
  7. 157
      script/batch_auto_obj_bake_vertex_ply.py
  8. 91
      script/ftp.py
  9. 92
      script/get_preview_png.py
  10. 44
      script/get_right_preview.py
  11. 288
      script/need.txt
  12. 70
      script/service.py
  13. 2017218
      script/simplified_mesh.obj
  14. 54
      script/test.py
  15. 33
      script/test1.py
  16. 124
      script/turn_around.py
  17. 52
      script/upload_and_clear_oss.py
  18. 259
      script/url.txt
  19. 69
      test.py
  20. 21
      test1.py
  21. 124
      tools/test.py

1
.gitignore vendored

@ -0,0 +1 @@
libs/__pycache__

30
libs/config.py

@ -18,17 +18,37 @@ ali_oss = {
oss_bucket = oss2.Bucket(oss2.Auth(ali_oss['access_key_id'], ali_oss['access_key_secret']), ali_oss['endpoint'], ali_oss['bucket_name']) oss_bucket = oss2.Bucket(oss2.Auth(ali_oss['access_key_id'], ali_oss['access_key_secret']), ali_oss['endpoint'], ali_oss['bucket_name'])
redis_remote = redis.Redis(host='106.14.158.208', password='kcV2000', port=6379, db=6) redis_remote = redis.Redis(host='106.14.158.208', password='kcV2000', port=6379, db=6)
redis_local = redis.Redis(host='172.16.20.13', password='ph2008', port=6379, db=0) redis_local = redis.Redis(host='172.31.1.254', password='', port=6379, db=0)
redis_local_common = redis.Redis(host='172.16.20.13', password='ph2008', port=6379, db=1) redis_local_common = redis.Redis(host='172.31.1.254', password='', port=6379, db=1)
mysql_local = { mysql_local = {
"host": "172.16.20.13", "host": '172.31.1.254',#"172.16.20.13",
"port": 3306, "port": 23306,
"user": "pi", "user": "pi",
"password": "ph2008", "password": "ph2008",
"db": "suwa3d", "db": "suwa3d",
"charset": "utf8mb4" "charset": "utf8mb4"
} }
mysql_gpu = {
"host": 'rm-uf64l0683d2t2jt1c3o.mysql.rds.aliyuncs.com',
"port": 3306,
"user": "airepair",
"password": "Ai_repair@suwa3d",
"db": "ai_repair",
"charset": "utf8"
}
mysql_dong = {
"host": "172.31.1.254",
"port": 13306,
"user": "api",
"password": "api2022",
"db": "new_suwa3d",
"charset": "utf8mb4"
}
if platform.system() == 'Windows': if platform.system() == 'Windows':
workdir = 'D:\\' workdir = 'D:\\'
sharedir = 'E:\\' sharedir = 'E:\\'
@ -137,4 +157,4 @@ high_host = ["R11","R12"]
low_host = ["R13","R14","R15","R16","R17"] low_host = ["R13","R14","R15","R16","R17"]
#不参与贴图的照片,使用的时候还需要增加指令 python main_step1.py 123 no_texture #不参与贴图的照片,使用的时候还需要增加指令 python main_step1.py 123 no_texture
noTextureColorPics = ["13", "23", "31", "52", "72", "82", "142", "173"] # 昆山老數據不慘與貼圖["134","135","136","142","143","14","15","16","24","25","26","44","45"] noTextureColorPics = ["13", "23", "31", "52", "72", "82", "142", "173"] #["134","135","136","142","143","14","15","16","24","25","26","44","45"]

24
libs/libs.py

@ -307,3 +307,27 @@ def diff_time(start_time):
m, s = divmod(diff, 60) m, s = divmod(diff, 60)
return f'{int(m)}{int(s)}' return f'{int(m)}{int(s)}'
def down_obj_from_oss_for_fix(workdir, pid, action):
if os.path.exists(os.path.join(workdir, action, pid)):
print(f'目录{os.path.join(workdir, action, pid)}已存在,跳过')
return
else:
os.makedirs(os.path.join(workdir, action, pid))
# 根据前缀获取文件列表
prefix = f'objs/{action}/{pid}/'
filelist = oss2.ObjectIteratorV2(config.oss_bucket, prefix=prefix)
print('正在下载:', prefix)
obj_filename = ""
for file in filelist:
filename = file.key.split('/')[-1]
if filename.endswith(f'{pid}.obj') == False:
continue
if filename.endswith('.obj'):
obj_filename = filename
# print('正在下载:', file.key)
localfile = os.path.join(workdir, action, pid, filename)
config.oss_bucket.get_object_to_file(file.key, localfile)
return obj_filename

213
libs/libs_db_temp.py

@ -0,0 +1,213 @@
# mysql数据库常用任务函数封装
import pymysql, socket, time
import config
#公共连接库
def pymysqlAlias():
return pymysql.connect(
host=config.mysql_dong['host'],
port=config.mysql_dong['port'],
user=config.mysql_dong['user'],
password=config.mysql_dong['password'],
db=config.mysql_dong['db'],
charset=config.mysql_dong['charset'],)
# 获取新的任务
def get_task_by_level():
try:
with pymysqlAlias() as conn:
cursor = conn.cursor()
sql = f'select pid from pid_base_fix where status = 0 order by level desc, id asc limit 1'
# print(f'sql: {sql}')
cursor.execute(sql)
data = cursor.fetchone()
if data:
return data[0]
else:
return ''
except Exception as e:
print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())} get_task_by_level()异常: {str(e)}")
return ''
# 开始任务
def update_fix_status(pid,status):
try:
with pymysqlAlias() as conn:
cursor = conn.cursor()
hostname = socket.gethostname()
sql = f'update pid_base_fix set status = {status},createTime = now(), updateTime = now() where status = 0 and pid = {pid}'
print(f'开始任务sql: {sql}')
cursor.execute(sql)
conn.commit()
except Exception as e:
print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())} 执行update_fix_status()异常: {str(e)}")
# # 获取新的任务
# def get_task(task_type):
# try:
# with pymysqlAlias() as conn:
# cursor = conn.cursor()
# sql = f'select task_key from tasks where status = 0 order by priority desc, id asc limit 1 for update'
# # print(f'sql: {sql}')
# cursor.execute(sql)
# data = cursor.fetchone()
# if data:
# return data[0]
# else:
# return ''
# except Exception as e:
# print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())} 执行get_task({task_type})异常: {str(e)}")
# return ''
# # 新增新的任务
# def add_task(data):
# try:
# with pymysqlAlias() as conn:
# cursor = conn.cursor()
# #判断是否是昆山教学的,是的话优先级设置为默认
# if data["psid"] == '85':
# sql = f'insert into tasks (task_type, task_key,studio_id) values ("{data["task_type"]}", "{data["task_key"]}","{data["psid"]}")'
# else:
# sql = f'insert into tasks (task_type, task_key, priority,studio_id) values ("{data["task_type"]}", "{data["task_key"]}", {data["priority"]},"{data["psid"]}")'
# # print(f'sql: {sql}')
# cursor.execute(sql)
# conn.commit()
# except Exception as e:
# print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())} 执行add_task({data})异常: {str(e)}")
# #新增任务到分布式处理任务表中 {"task_type":key,"task_key":pid,"psid":psid}
# def add_task_distributed(data):
# flag = isInTaskDistributed(data["task_key"])
# if flag:
# return "already"
# try:
# with pymysqlAlias() as conn:
# cursor = conn.cursor()
# sql = f'insert into task_distributed (task_type, task_key, priority,created_at,studio_id) values ("{data["task_type"]}", "{data["task_key"]}", "{data["priority"]}","{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}","{data["psid"]}")'
# cursor.execute(sql)
# conn.commit()
# except Exception as e:
# print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())} 执行add_task_distributed({data})异常: {str(e)}")
# # 开始任务
# def start_task(data):
# try:
# with pymysqlAlias() as conn:
# cursor = conn.cursor()
# hostname = socket.gethostname()
# sql = f'update tasks set status = 1, hostname = "{hostname}", started_at = now(), updated_at = now() where status = 0 and task_key = {data["task_key"]}'
# print(f'开始任务sql: {sql}')
# cursor.execute(sql)
# conn.commit()
# except Exception as e:
# print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())} 执行start_task({data})异常: {str(e)}")
# # 完成任务
# def finish_task(data):
# try:
# with pymysqlAlias() as conn:
# cursor = conn.cursor()
# hostname = socket.gethostname()
# sql = f'update tasks set status = 2, hostname = "{hostname}", finished_at = now(), updated_at = now() where status = 1 and task_key = "{data["task_key"]}" '
# # print(f'sql: {sql}')
# cursor.execute(sql)
# conn.commit()
# except Exception as e:
# print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())} 执行finish_task({data})异常: {str(e)}")
# # 根据影棚ID 获取影棚的配置,如果没有指定的配置,则返回默认配置
# def get_floor_sticker_distances(psid):
# try:
# with pymysqlAlias() as conn:
# cursor = conn.cursor()
# sql = f'select a.studio_id,value from floor_sticker_link_studio as a left join floor_sticker_distances as b on a.floor_name = b.name where a.studio_id in (0,{psid})'
# cursor.execute(sql)
# result = cursor.fetchall()
# if len(result) == 1:
# return result[0][1]
# if len(result) == 2:
# for item in result:
# if str(item[0]) == str(psid):
# return item[1]
# return "error-配置异常,该影棚有多个地贴配置"
# except Exception as e:
# print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())} 执行get_floor_sticker_distances()异常: {str(e)}")
# return "error"
# #判断是否要走新的建模系统
# def is_new_make_psid(psid):
# try:
# with pymysqlAlias() as conn:
# cursor = conn.cursor()
# sql = f'select count(*) from new_make_psid where studio_id = {psid}'
# print(f'sql: {sql}')
# cursor.execute(sql)
# result = cursor.fetchone()
# if result[0] > 0:
# return True
# else:
# return False
# except Exception as e:
# print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())} 执行is_new_make_psid()异常: {str(e)}")
# return "error"
# #判断影棚是否走的新的建模系统,不是的话修改成走新的建模系统
# def change_to_new_make_psid(psid):
# try:
# with pymysqlAlias() as conn:
# cursor = conn.cursor()
# sql = f'select count(*) from new_make_psid where studio_id = {psid}'
# cursor.execute(sql)
# result = cursor.fetchone()
# if result[0] == 0:
# sql = f'insert into new_make_psid (studio_id,createTime) values ({psid},now())'
# cursor.execute(sql)
# conn.commit()
# print(f'修改影棚{psid}为走新的建模系统')
# except Exception as e:
# print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())} 执行change_to_new_make_psid()异常: {str(e)}")
# return "error"
# #判断影棚走分布式的建模系统 还是走原来的建模系统
# def isStudioConfigDistribute(psid):
# try:
# with pymysqlAlias() as conn:
# cursor = conn.cursor()
# sql = f'select count(*) from studio_config_distribute where studio_id = {psid} and status = 1'
# cursor.execute(sql)
# result = cursor.fetchone()
# if result[0] == 0:
# return False
# else:
# return True
# except Exception as e:
# print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())} 执行change_to_new_make_psid()异常: {str(e)}")
# return "error"
# #判断是否已经存在了
# def isInTaskDistributed(task_key):
# try:
# with pymysqlAlias() as conn:
# cursor = conn.cursor()
# sql = f'select count(*) from task_distributed where status = 0 and task_key = "{task_key}"'
# cursor.execute(sql)
# result = cursor.fetchone()
# if result[0] == 0:
# return False
# else:
# return True
# except Exception as e:
# print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())} 执行isInTaskDistributed()异常: {str(e)}")
# return "error"

273
script/bacth_obj_bake_vertex_high_ply.py

@ -0,0 +1,273 @@
import os, sys, time, argparse, requests, json, re, oss2
import bpy, bmesh
import open3d as o3d
import numpy as np
# import cupy as cp
from mathutils import Matrix
import math
import logging
import matplotlib.pyplot as plt
def remove_nan_verts(obj):
'''删除模型中空坐标的顶点'''
# obj = bpy.context.active_object
if obj.mode == 'EDIT':
bm = bmesh.from_edit_mesh(obj.data)
else:
bm = bmesh.new()
bm.from_mesh(obj.data)
nans = [v for v in bm.verts if any(c != c for c in v.co)]
bmesh.ops.delete(bm, geom=nans, context='VERTS')
degenerates = [f for f in bm.faces if len(f.verts) < 3]
bmesh.ops.delete(bm, geom=degenerates, context='FACES')
if obj.mode == 'EDIT':
bmesh.update_edit_mesh(obj.data)
else:
bm.to_mesh(obj.data)
obj.data.update()
print("NAN vertices and degenerate faces removed.")
def getHeadCount(pid):
get_printinfo_url = 'https://mp.api.suwa3d.com/api/customerP3dLog/printInfo'
res = requests.get(get_printinfo_url, params={'id': pid})
print('get_printinfo_url:', res.url)
print('res:', res.text)
if res.status_code != 200:
print('获取人数失败,程序退出')
exit(1)
res = json.loads(res.text)
return res['data']['headcount']
def get_obj_bake_vertex_ply(obj_filepath, save_ply_path):
start_time = time.time()
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: Getting ply vertex from {obj_filepath}')
bpy.ops.object.select_all(action='DESELECT')
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete(use_global=False, confirm=False)
bpy.ops.wm.obj_import(filepath=obj_filepath)
obj_original = [obj for obj in bpy.data.objects if obj.type == 'MESH'][0]
bpy.context.view_layer.objects.active = obj_original
obj_original.select_set(True)
pid = obj_original.name
obj_num_vertices = len(obj_original.data.vertices)
# print(f"模型 {pid} 顶点数量:", len(obj_original.data.vertices))
# 选择新分离出来的网格对象,并将该对象设为进活动对象
bpy.ops.object.select_all(action='DESELECT')
bpy.context.view_layer.objects.active = obj_original
obj_original.select_set(True)
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: Split foot time: ', time.time() - start_time)
start_time = time.time()
# 表面细分Subdivision Surface,如果细分后定点数目大于目标数目,停止循环细分
# target_verts = len(obj_original.data.vertices) * 8
try:
target_verts = getHeadCount(pid) * 2000000
except TypeError as e:
return 0
mesh_data = obj_original.data
obj_original_name = obj_original.name
# Blender 网格对象的顶点数据转换为 Open3D 格式
o3d_mesh = o3d.geometry.TriangleMesh()
o3d_mesh.vertices = o3d.utility.Vector3dVector([v.co for v in mesh_data.vertices])
o3d_mesh.triangles = o3d.utility.Vector3iVector([f.vertices for f in mesh_data.polygons])
o3d_mesh.compute_vertex_normals() # 计算顶点法线
# open3d 细分操作
for i in range(2, 8):
mesh_subdivided = o3d_mesh.subdivide_loop(number_of_iterations=i)
subdivision_vertex_count = len(mesh_subdivided.vertices)
if subdivision_vertex_count > target_verts:
break
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: Subdivision time: ', time.time() - start_time)
start_time = time.time()
# open3d 减面操作
# 官网文档介绍简化网格不能保证一定会达到这个数字
target_triangles = target_verts * 2
mesh_smp = mesh_subdivided.simplify_quadric_decimation(target_number_of_triangles=target_triangles)
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: Decimation time: ', time.time() - start_time)
start_time = time.time()
# 将open3d网格转换回blender网格
o3d_to_blender_mesh = bpy.data.meshes.new(name=f"{obj_original_name}_decimation")
o3d_to_blender_mesh.from_pydata(mesh_smp.vertices, [], mesh_smp.triangles)
o3d_to_blender_mesh.update()
obj_open3d = bpy.data.objects.new(f"{obj_original_name}_decimation", o3d_to_blender_mesh)
# 设置新对象的位置和旋转信息,等于原始模型的信息
obj_open3d.location = obj_original.location
obj_open3d.rotation_euler = obj_original.rotation_euler
obj_open3d.scale = obj_original.scale
bpy.context.collection.objects.link(obj_open3d)
# 开始将obj_mesh的贴图颜色烘焙到open3d模型上
# 复制对象作为罩体
obj_cage = obj_open3d.copy()
obj_cage.data = obj_open3d.data.copy()
bpy.context.collection.objects.link(obj_cage)
obj_cage.name = f"{obj_original_name}_cage"
bpy.ops.object.select_all(action='DESELECT')
bpy.context.view_layer.objects.active = obj_open3d
obj_open3d.select_set(True)
bpy.ops.object.mode_set(mode='EDIT')
bpy.context.scene.tool_settings.use_uv_select_sync = True # 同步3D_View和UV编辑模式选中顶点部分
bpy.ops.uv.smart_project()
bpy.ops.uv.select_overlap()
bpy.ops.uv.unwrap(method='ANGLE_BASED', margin=0)
bpy.ops.uv.select_all(action='SELECT')
bpy.ops.uv.average_islands_scale()
bpy.ops.uv.pack_islands(margin=0)
bpy.ops.object.mode_set(mode='OBJECT')
# 新建open3d模型的材质
open3dMat = bpy.data.materials.new(name='Mat_open3d')
obj_open3d.data.materials.append(open3dMat)
open3dMat.use_nodes = True
nodes = open3dMat.node_tree.nodes
prin_bsdf_node = nodes.get("Principled BSDF")
# 创建新的贴图对象
tex_image_node = nodes.new("ShaderNodeTexImage")
tex_image = bpy.data.images.new(name="o3d_teximage", width=8192, height=8192)
tex_image_node.image = tex_image
tex_image_node.location = (-400, 200)
tex_image_node.select = True # 节点选中状态
tex_image_node.select = True # 节点为活动状态
links = open3dMat.node_tree.links
bpy.context.object.active_material = open3dMat
bpy.ops.object.material_slot_select()
bpy.ops.object.material_slot_assign()
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: Prepare bake data time: ', time.time() - start_time)
start_time = time.time()
# 烘焙操作
bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.cycles.device = 'GPU'
bpy.context.scene.cycles.preview_samples = 1
bpy.context.scene.cycles.samples = 1
bpy.context.scene.cycles.bake_type = 'DIFFUSE'
bpy.context.scene.render.bake.use_pass_direct = False
bpy.context.scene.render.bake.use_pass_indirect = False
bpy.context.scene.render.bake.use_pass_color = True
bpy.context.scene.render.bake.use_selected_to_active = True
bpy.context.scene.render.bake.use_cage = True
bpy.context.scene.render.bake.cage_object = bpy.data.objects[obj_cage.name]
bpy.context.scene.render.bake.target = 'IMAGE_TEXTURES'
# 添加置换修改器,不能应用
bpy.ops.object.select_all(action='DESELECT')
bpy.context.view_layer.objects.active = obj_cage
obj_cage.select_set(True)
bpy.ops.object.modifier_add(type='DISPLACE')
bpy.context.object.modifiers["Displace"].mid_level = 0.995
bpy.ops.object.modifier_apply(modifier="Displace")
bpy.ops.object.select_all(action='DESELECT')
bpy.context.view_layer.objects.active = obj_original
obj_original.select_set(True)
bpy.context.view_layer.objects.active = obj_open3d
obj_open3d.select_set(True)
bpy.ops.object.bake(type='DIFFUSE') # 开始 Bake
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: Bake DIFFUSE time: ', time.time() - start_time)
start_time = time.time()
links.new(tex_image_node.outputs[0], prin_bsdf_node.inputs[0])
bpy.data.objects.remove(obj_original, do_unlink=True)
bpy.data.objects.remove(obj_cage, do_unlink=True)
# 添加颜色属性
bpy.ops.geometry.color_attribute_add()
# 节点的创建:
# nodes = bpy.context.active_object.active_material.node_tree.nodes
# links = bpy.context.active_object.active_material.node_tree.links
tex_coord = nodes.new("ShaderNodeTexCoord")
Mapping = nodes.new('ShaderNodeMapping')
vertex_color = nodes.new("ShaderNodeVertexColor")
tex_coord.location = (-800, 600)
Mapping.location = (-500, 200)
vertex_color.location = (-200, 800)
# 节点之间的连接:
# 纹理坐标的UV 连接 映射的矢量;映射的矢量 连接 纹理贴图的矢量;原理化BSDF删除;纹理贴图的矢量 连接 表(曲)面。
links.new(tex_coord.outputs[2], nodes['Mapping'].inputs[0])
links.new(Mapping.outputs[0], nodes['Image Texture'].inputs[0])
principled_bsdf = nodes.get("Principled BSDF")
nodes.remove(principled_bsdf)
links.new(nodes['Image Texture'].outputs[0], nodes['Material Output'].inputs[0])
# 4.渲染烘焙相关操作
bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.cycles.device = 'GPU'
bpy.context.scene.cycles.preview_samples = 1
bpy.context.scene.cycles.samples = 1
bpy.context.scene.cycles.bake_type = 'EMIT'
bpy.context.scene.render.bake.use_selected_to_active = False
bpy.context.scene.render.bake.target = 'VERTEX_COLORS'
bpy.ops.object.bake(type='EMIT') # 开始 Bake
# 连接节点 Color Attribute 和 节点 Material Output
links.new(nodes['Color Attribute'].outputs[0], nodes['Material Output'].inputs[0])
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: Bake EMIT time: ', time.time() - start_time)
start_time = time.time()
# 清除顶点为nan的无效数据
bpy.ops.object.select_all(action='DESELECT')
bpy.context.view_layer.objects.active = obj_open3d
obj_open3d.select_set(True)
remove_nan_verts(obj_open3d)
# 5.输出模型
# bpy.ops.wm.save_as_mainfile(filepath='/data/datasets/plys/121614.bend')
bpy.ops.wm.ply_export(filepath=save_ply_path, apply_modifiers=True, export_selected_objects=True, export_uv=False,
export_normals=False, export_colors='SRGB', export_triangulated_mesh=False, ascii_format=True)
bpy.data.objects.remove(obj_open3d, do_unlink=True)
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: Save ply time: ', time.time() - start_time)
return obj_num_vertices
if __name__ == '__main__':
# workdir = '/data/datasets/suwa_cut/data/auto/'
# output = '/data/datasets/plys/auto/'
workdir = 'G:\obj_fix\print'
output = 'G:\obj_fix\ply\whole_obj_bake_vertex_high_ply'
directory = f'G:\obj_fix/print/right'
#遍历获取 G:\obj_fix\print\right 目录的文件,根据文件名获取 pid
for file_name in os.listdir(directory):
# 获取文件的完整路径
file_path = os.path.join(directory, file_name)
# 检查是否是文件
if os.path.isfile(file_path):
#
arrFileName = file_name.split('_')
pid = arrFileName[0]
if int(pid) == 0:
continue
print(f"File: {file_name}, PID: {pid}")
#判断文件是否存在
file_path = os.path.join(output, f'{pid}.ply')
if os.path.exists(file_path) and os.path.isfile(file_path):
print("文件已存在,跳过循环!!!")
continue
obj_filepath = os.path.join(workdir, f'{pid}/{pid}.obj')
save_ply_path = os.path.join(output, f'{pid}.ply')
if not os.path.exists(obj_filepath):
print(f"{obj_filepath} 文件不存在,跳过循环!!!")
continue
obj_num_vertices = get_obj_bake_vertex_ply(obj_filepath, save_ply_path)
if obj_num_vertices == 0:
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: 模型 {pid} 程序getHeadCount()无法找到模型人数!总共运行时间: ', time.time() - start_time0)
logging.info(f'模型 {pid} 顶点数量: {obj_num_vertices},程序getHeadCount()无法找到模型人数!,程序总共运行时间: {time.time() - start_time0:.2f}')
continue

296
script/base_data_fix.py

@ -0,0 +1,296 @@
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

157
script/batch_auto_obj_bake_vertex_ply.py

@ -0,0 +1,157 @@
import os, sys, time, argparse, requests, json, re, oss2
import bpy, bmesh
import open3d as o3d
import numpy as np
# import cupy as cp
from mathutils import Matrix
import math
import logging
import matplotlib.pyplot as plt
def get_auto_obj_bake_vertex_ply(obj_filepath, save_ply_path):
start_time = time.time()
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: Getting ply vertex from {obj_filepath}')
bpy.ops.object.select_all(action='DESELECT')
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete(use_global=False, confirm=False)
bpy.ops.wm.obj_import(filepath=obj_filepath)
obj_original = [obj for obj in bpy.data.objects if obj.type == 'MESH'][0]
bpy.context.view_layer.objects.active = obj_original
obj_original.select_set(True)
pid = obj_original.name
obj_num_vertices = len(obj_original.data.vertices)
# print(f"模型 {pid} 顶点数量:", len(obj_original.data.vertices))
# 选择新分离出来的网格对象,并将该对象设为进活动对象
bpy.ops.object.select_all(action='DESELECT')
bpy.context.view_layer.objects.active = obj_original
obj_original.select_set(True)
# 添加颜色属性
bpy.ops.geometry.color_attribute_add()
# 节点的创建:
nodes = bpy.context.active_object.active_material.node_tree.nodes
links = bpy.context.active_object.active_material.node_tree.links
tex_coord = nodes.new("ShaderNodeTexCoord")
Mapping = nodes.new('ShaderNodeMapping')
vertex_color = nodes.new("ShaderNodeVertexColor")
tex_coord.location = (-800, 600)
Mapping.location = (-500, 200)
vertex_color.location = (-200, 600)
# 节点之间的连接:
# 纹理坐标的UV 连接 映射的矢量;映射的矢量 连接 纹理贴图的矢量;原理化BSDF删除;纹理贴图的矢量 连接 表(曲)面。
links.new(tex_coord.outputs[2], nodes['Mapping'].inputs[0])
links.new(Mapping.outputs[0], nodes['Image Texture'].inputs[0])
principled_bsdf = nodes.get("Principled BSDF")
nodes.remove(principled_bsdf)
links.new(nodes['Image Texture'].outputs[0], nodes['Material Output'].inputs[0])
# 4.渲染烘焙相关操作
bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.cycles.device = 'GPU'
bpy.context.scene.cycles.preview_samples = 1
bpy.context.scene.cycles.samples = 1
bpy.context.scene.cycles.bake_type = 'EMIT'
bpy.context.scene.render.bake.use_selected_to_active = False
bpy.context.scene.render.bake.target = 'VERTEX_COLORS'
bpy.ops.object.bake(type='EMIT') # 开始 Bake
# 连接节点 Color Attribute 和 节点 Material Output
links.new(nodes['Color Attribute'].outputs[0], nodes['Material Output'].inputs[0])
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: Bake EMIT time: ', time.time() - start_time)
start_time = time.time()
# 5.输出模型
# bpy.ops.wm.save_as_mainfile(filepath='/data/datasets/plys/121614.bend')
bpy.ops.wm.ply_export(filepath=save_ply_path, apply_modifiers=True, export_selected_objects=True, export_uv=False,
export_normals=False, export_colors='SRGB', export_triangulated_mesh=False, ascii_format=True)
bpy.data.objects.remove(obj_original, do_unlink=True)
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: Save ply time: ', time.time() - start_time)
return obj_num_vertices
if __name__ == '__main__':
# workdir = '/data/datasets/suwa_cut/data/auto/'
# output = '/data/datasets/plys/auto/'
workdir = 'G:\obj_fix\print'
output = 'G:\obj_fix\ply\whole_obj_bake_vertex_high_ply'
directory = f'G:\obj_fix/print/right'
#遍历获取 G:\obj_fix\print\right 目录的文件,根据文件名获取 pid
for file_name in os.listdir(directory):
# 获取文件的完整路径
file_path = os.path.join(directory, file_name)
# 检查是否是文件
if os.path.isfile(file_path):
#
arrFileName = file_name.split('_')
pid = arrFileName[0]
if int(pid) == 0:
continue
print(f"File: {file_name}, PID: {pid}")
#判断文件是否存在
file_path = os.path.join(output, f'{pid}.ply')
if os.path.exists(file_path) and os.path.isfile(file_path):
print("文件已存在,跳过循环!!!")
continue
obj_filepath = os.path.join(workdir, f'{pid}/{pid}.obj')
save_ply_path = os.path.join(output, f'{pid}.ply')
if not os.path.exists(obj_filepath):
print(f"{obj_filepath} 文件不存在,跳过循环!!!")
continue
obj_num_vertices = get_auto_obj_bake_vertex_ply(obj_filepath, save_ply_path)
if obj_num_vertices == 0:
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: 模型 {pid} 程序getHeadCount()无法找到模型人数!总共运行时间: ', time.time() - start_time0)
logging.info(f'模型 {pid} 顶点数量: {obj_num_vertices},程序getHeadCount()无法找到模型人数!,程序总共运行时间: {time.time() - start_time0:.2f}')
continue
# # 从文件名中提取 pid
# pid = extract_pid(file_name)
# if pid:
# print(f"File: {file_name}, PID: {pid}")
# else:
# print(f"Unable to extract PID from file: {file_name}")
# return
# listdir_pids = os.listdir(workdir)
# for pid in listdir_pids:
# file_path = os.path.join(output, f'{pid}/{pid}.ply')
# if os.path.exists(file_path) and os.path.isfile(file_path):
# print("文件已存在,跳过循环!!!")
# continue
# print(pid)
# logging.basicConfig(filename=f'/data/datasets/plys/auto_vertex_time.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# start_time0 = time.time()
# print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: 模型 {pid} 开始运行时间: ', start_time0)
# # 判断输出目录是否存在
# if not os.path.exists(os.path.join(output, f'{pid}/')):
# os.makedirs(os.path.join(output, f'{pid}/'))
# obj_filepath = os.path.join(workdir, f'{pid}/{pid}_cpd.obj')
# save_ply_path = os.path.join(output, f'{pid}/{pid}.ply')
# if not os.path.exists(obj_filepath):
# print(f"{obj_filepath} 文件不存在,跳过循环!!!")
# continue
# obj_num_vertices = get_auto_obj_bake_vertex_ply(obj_filepath, save_ply_path)
# if obj_num_vertices == 0:
# print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: 模型 {pid} 程序getHeadCount()无法找到模型人数!总共运行时间: ', time.time() - start_time0)
# logging.info(f'模型 {pid} 顶点数量: {obj_num_vertices},程序getHeadCount()无法找到模型人数!,程序总共运行时间: {time.time() - start_time0:.2f} 秒')
# continue
# print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: 模型 {pid} 顶点数量: {obj_num_vertices} 程序总共运行时间: ', time.time() - start_time0)
# logging.info(f'模型 {pid} 顶点数量: {obj_num_vertices},程序总共运行时间: {time.time() - start_time0:.2f} 秒')
# # 退出 Blender 并释放资源
# bpy.ops.wm.quit_blender()

91
script/ftp.py

@ -0,0 +1,91 @@
import paramiko
import os
# 使用示例
sftp_host = "172.31.1.3" # SFTP 服务器地址
sftp_port = 22 # SFTP 端口号
sftp_user = 'gpu' # SFTP 登录用户名
sftp_passwd = '2024' # SFTP 登录密码
# 获取当前文件上一层目录,即项目目录 make2 底下
local_root_path = "G:\\obj_fix\print"
# 定义函数来递归遍历文件夹下的所有文件
def list_files(directory):
for root, dirs, files in os.walk(directory):
for file in files:
yield os.path.join(root, file)
def sftp_upload(sftp_host, sftp_port, sftp_user, sftp_passwd, local_file, remote_file):
# 创建 SSH 客户端对象
ssh_client = paramiko.SSHClient()
try:
# 设置自动添加主机密钥
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接到 SFTP 服务器
ssh_client.connect(sftp_host, port=sftp_port, username=sftp_user, password=sftp_passwd)
# 创建 SFTP 客户端对象
sftp_client = ssh_client.open_sftp()
# 判断 local_file 是文件还是目录
if os.path.isdir(local_file):
try:
# 如果远程目录不存在,则创建
sftp_client.mkdir(remote_file)
except IOError:
# 目录已存在,忽略
pass
# 切换至远程目录
sftp_client.chdir(remote_file)
# 遍历本地目录
for file_name in os.listdir(local_file):
local_path = os.path.join(local_file, file_name)
if os.path.isfile(local_path):
# 如果是文件,上传文件
sftp_client.put(local_path, file_name)
else:
# 如果是文件,直接上传文件
sftp_client.put(local_file, remote_file)
print("上传成功")
except Exception as e:
print(f"上传文件失败:{e}")
finally:
# 关闭 SFTP 客户端和 SSH 连接
sftp_client.close()
ssh_client.close()
if __name__ == '__main__':
nums = 0
#遍历 local_root_path 下的所有文件
for file_path in list_files(local_root_path):
if "around" in file_path:
continue
if "_old.obj" in file_path:
# if ".obj" not in file_path:
# continue
arrTemp = file_path.split('\\')
pid = arrTemp[len(arrTemp)-2]
nums += 1
# # pid = "164"
# 本地文件路径
dirPath = f'{local_root_path}/{pid}/{pid}.obj'
# 远程服务的路径
remote_file = f"/data/datasets/obj_fix/{pid}/{pid}.obj"
sftp_upload(sftp_host, sftp_port, sftp_user, sftp_passwd, dirPath, remote_file)
print(pid,file_path,"---剩余---",524 - nums)

92
script/get_preview_png.py

@ -0,0 +1,92 @@
import platform,sys,redis,time,requests,json,atexit
import os, sys, time, argparse, requests, json, re, oss2
import bpy
import open3d as o3d
import shutil
import psutil
#生成预览图
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 = 50
height = 100
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 list_files(directory):
for root, dirs, files in os.walk(directory):
for file in files:
yield os.path.join(root, file)
#生成预览图
target_folder = 'G://obj_fix/print/'
source_folder = 'G://obj_fix/print/preview'
#遍历文件夹下的所有文件
nums = 0
for file_path in list_files(target_folder):
if ".obj" not in file_path:
continue
print("文件路径:",file_path)
#判断文件是否存在
if not os.path.exists(file_path):
continue
print(file_path)
arrData = file_path.split('/')
pid = arrData[len(arrData)-2]
#判断封面图片是否存在
# if os.path.exists(f'{target_folder}/{pid}_preview.png'):
# print(f'{pid}_preview.png 已存在,跳过循环!!!')
# continue
nums += 1
print(f"正在处理{pid}","--剩余--",1530 - nums)
create_preview(f'{file_path}',f'{source_folder}/{pid}_preview.png',pid)

44
script/get_right_preview.py

@ -0,0 +1,44 @@
import os
import shutil
#遍历 G:\obj_fix\print\wrong 文件 获取到pid
workdir = 'G:\obj_fix\print'
# output = 'G:\obj_fix\ply\whole_obj_bake_vertex_high_ply'
directory = f'G:\obj_fix/print/wrong'
#遍历获取 G:\obj_fix\print\right 目录的文件,根据文件名获取 pid
arrWrongFiles = []
for file_name in os.listdir(directory):
# # 获取文件的完整路径
# file_path = os.path.join(directory, file_name)
# # 检查是否是文件
# if os.path.isfile(file_path):
# #
arrFileName = file_name.split('_')
pid = arrFileName[0]
if int(pid) == 0:
continue
arrWrongFiles.append(pid)
#遍历 G:\obj_fix\print\preview 文件 获取到pid
directory = f'G:\obj_fix/print/preview'
for file_name in os.listdir(directory):
arrFileName = file_name.split('_')
pid = arrFileName[0]
if int(pid) == 0:
continue
if pid in arrWrongFiles:
continue
#判断right目录中是否已经存在该pid的文件
if os.path.exists(f'G:\obj_fix/print/right/{file_name}'):
continue
print("new_pid",pid)
#不在arrWrongFiles中的pid,就是正确的pid要复制到right目录
filePath = os.path.join(directory, file_name)
shutil.copy(filePath, f'G:\obj_fix/print/right/{file_name}')

288
script/need.txt

@ -0,0 +1,288 @@
31013
78387
40918
71701
27553
58122
55114
25093
9846
70756
128719
17388
49934
56750
71421
55844
136602
136603
136925
31450
71326
30624
56802
4417
55367
119772
75416
71422
66521
26848
55083
77226
42595
8141
115162
66531
11997
77960
115302
68700
124636
79333
54701
70807
65918
64088
127455
71415
11797
68807
115123
53804
24775
75402
30663
68349
44322
14301
55076
14216
68699
56784
55030
70532
13084
48197
79263
14475
44845
14094
15963
29506
117004
88074
49404
62516
57762
76289
25568
120406
9177
13073
70754
55082
83698
77516
125118
25043
78384
71356
56559
70792
68692
115028
26384
8171
23805
14148
82460
24765
82496
115074
120416
39732
45480
67655
22155
77957
29507
83844
56799
31596
40613
24766
100270
104867
21807
56781
21007
136602
55011
22204
77964
16074
56877
68724
13160
136302
83715
121495
77431
12177
68906
24784
30617
87849
56754
55370
42781
12981
70732
121614
30660
8852
31012
78376
75405
9023
136603
69798
55092
8145
71361
81419
55887
83761
74624
82571
15707
115228
70746
83983
29805
71318
135850
83759
29489
63115
19338
16012
29796
15012
48250
8160
75408
48477
68718
21780
55860
77221
20197
115017
86196
55730
82483
64739
13154
8121
22159
55372
86211
44623
11845
68925
106929
31010
31442
71321
68940
25200
50370
70729
49935
68916
24780
39522
42047
20675
78385
68688
13120
8953
33899
13692
79331
76300
30638
71323
19405
48880
56797
56654
9181
115051
46352
10873
27534
55075
136357
55084
11881
68735
77972
8124
13161
70812
30705
55081
123599
31986
36791
55849
47752
55021
128446
30843
71407
41320
57168
71395
16078
20203
65653
27214
52884
71404
24772
115042
55090
78381
43054
125097
136925
68730
68821
68926
61764
11676
43059
98894
80445
84547
83707
82435
83729
82440
83712
80166
80007
82481
83727
85652
86232
86252
83756
82511
87649
82486

70
script/service.py

@ -0,0 +1,70 @@
from flask import Flask, jsonify, request
import os
from flask_cors import CORS
app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
# 定义函数来递归遍历文件夹下的所有文件
def list_files(directory):
for root, dirs, files in os.walk(directory):
for file in files:
yield os.path.join(root, file)
# 更新数据
@app.route('/api/data/', methods=['GET'])
def update_data():
pid = request.args.get('pid')
angle = request.args.get('angle')
jump = request.args.get('jump')
if jump == "jump":
file_path = f'G:\obj_fix\print\wrong\{pid}_preview.png'
if not os.path.exists(file_path):
return "file not exists"
#重命名文件
new_file_path = f'G:\obj_fix\print\wrong\{pid}_preview_wait.png'
os.rename(file_path, new_file_path)
else:
if pid == "0":
return "pid is 0"
if str(angle[0]) == "0":
return "angle is 0"
file_path = f'G:\obj_fix\print\wrong\{pid}_preview.png'
if not os.path.exists(file_path):
return "file not exists"
#重命名文件
new_file_path = f'G:\obj_fix\print\wrong\{pid}_preview_{angle}.png'
os.rename(file_path, new_file_path)
#遍历 G:\obj_fix\print\wrong\ 文件夹下的所有文件
for file_path in list_files('G:\obj_fix\print\wrong'):
if "_preview.png" not in file_path:
continue
#获取pid 从 "G:\obj_fix\print\wrong\76289_preview_117.png" 中获取 "76289
pid = file_path.split('\\')[-1].split('_')[0]
return pid
# #组装链接
# url = f'https://mp.suwa3d.com/preview.html?platform=1&id={pid}&size=18cm_x1&angle=1#/'
# #将 url 写入文件
# with open('url.txt', 'a') as f:
# f.write(url + '\n')
#return jsonify({'pid': id1, 'angle': id2})
# for item in data:
# if item['id'] == data_id:
# item.update(request.get_json())
# return jsonify({'message': 'Data updated successfully'})
#return jsonify({'message': 'Data not found'}), 404
if __name__ == '__main__':
app.run(debug=True)

2017218
script/simplified_mesh.obj

File diff suppressed because it is too large Load Diff

54
script/test.py

@ -0,0 +1,54 @@
from pathlib import Path
import os
import shutil
# 指定要遍历的文件夹路径
folder_path = Path('G://obj_fix/print')
# 定义函数来递归遍历文件夹下的所有文件
def list_files(directory):
for root, dirs, files in os.walk(directory):
for file in files:
yield os.path.join(root, file)
# 指定要遍历的文件夹路径
# folder_path = folder_path
# 使用list_files函数来列出文件夹下的所有文件
nums = 0
for file_path in list_files(folder_path):
if "around" in file_path:
continue
if "_new.obj" not in file_path:
continue
#提取pid
arrTemp = file_path.split('\\')
pid = arrTemp[len(arrTemp)-2]
#判段是否存在 {pid}.obj 文件,存在的话就进行重命名
initObjPath = f'G://obj_fix/print/{pid}/{pid}.obj'
if not os.path.exists(initObjPath):
continue
#存在的话就重命名文件
old_file_path = f'G://obj_fix/print/{pid}/{pid}_old.obj'
os.rename(initObjPath, old_file_path)
newObjfilePath = f'G://obj_fix/print/{pid}/{pid}_new.obj'
os.rename(newObjfilePath, initObjPath)
# # 将 new.obj 文件复制到指定的文件夹下 G:\obj_fix\print\{pid}\
# source_obj = file_path
# target_obj = f'G://obj_fix/print/{pid}/{pid}_new.obj'
# print(f"当前正在处理{pid}")
# shutil.copy(source_obj, target_obj)
nums += 1
print(pid,file_path,nums)

33
script/test1.py

@ -0,0 +1,33 @@
import os
import shutil
folder_path = 'G:\\obj_fix\print'
# 遍历文件夹下的所有文件
# 定义函数来递归遍历文件夹下的所有文件
def list_files(directory):
for root, dirs, files in os.walk(directory):
for file in files:
yield os.path.join(root, file)
nums = 0
for file_path in list_files(folder_path):
if "_preview.png" not in file_path:
continue
print(file_path)
nums += 1
# #提取pid
# arrTemp = file_path.split('\\')
# pid = arrTemp[len(arrTemp)-2]
# #判断 G:\obj_fix\print\wrong\ 文件夹里 是否存在 {pid}_preview.png 文件
# filePath = f'G://obj_fix\print\wrong\{pid}_preview.png'
# #不存在跳过
# if not os.path.exists(filePath):
# continue
# #存在的话就重命名文件
# new_file_path = f'G://obj_fix\print\wrong\{pid}_preview_already_right.png'
# os.rename(filePath, new_file_path)
print(nums)

124
script/turn_around.py

@ -0,0 +1,124 @@
import numpy as np
import open3d as o3d
import math,os
#矫正模型的方向,目前只支持水平旋转,
#55084 55090 55092 55114 55367 55370 55372 55730 55844 55849 56559 56654 56750 75408
def rotate_vertex(x, y, z, axis, angle_degrees):
"""
围绕任意轴旋转顶点
axis是一个表示旋转轴的三元组 (ax, ay, az)
angle_degrees是旋转角度以度为单位
"""
# 将角度转换为弧度
angle_radians = math.radians(angle_degrees)
# 将旋转轴转换为单位向量
axis = np.array(axis)
axis = axis / np.linalg.norm(axis)
# 将顶点位置转换为向量
v = np.array([x, y, z])
# 应用罗德里格斯旋转公式
v_rotated = (v * math.cos(angle_radians) +
np.cross(axis, v) * math.sin(angle_radians) +
axis * np.dot(axis, v) * (1 - math.cos(angle_radians)))
return v_rotated.tolist()
def transform_obj_file(source_file, target_file, axis, angle_degrees):
"""
读取 OBJ 文件应用旋转然后将结果保存到另一个文件
"""
with open(source_file, 'r') as src:
lines = src.readlines()
with open(target_file, 'w') as tgt:
for line in lines:
if line.startswith('v '):
parts = line.split()
x, y, z = map(float, parts[1:4])
x_new, y_new, z_new = rotate_vertex(x, y, z, axis, angle_degrees)
tgt.write(f"v {x_new} {y_new} {z_new}\n")
else:
tgt.write(line)
def list_files(directory):
for root, dirs, files in os.walk(directory):
for file in files:
yield os.path.join(root, file)
# # #遍历文件夹下的所有文件
# folder_path = 'G://obj_fix/print/wrong'
# nums = 0
# rotate_axis = (0, 1, 0) # 比如绕X轴旋转
# for file_path in list_files(folder_path):
# #print(file_path) G://obj_fix/print/around/preview\9023_preview_117.png
# if "_preview.png" in file_path:
# continue
# if "_right.png" in file_path:
# continue
# if "_wait.png" in file_path:
# continue
# #获取pid 从 "G://obj_fix/print/around/preview\9023_preview_117.png" 中获取 9023 he 117
# arrData = file_path.split('\\')
# lastData = arrData[-1]
# arrLastData = lastData.split('_')
# if len(arrLastData) < 3:
# print(lastData)
# continue
# pid = arrLastData[0]
# angle = arrLastData[2].split('.')[0]
# #判断 angle 第一个数字是否为 0
# source_obj = f'G://obj_fix/print/{pid}/{pid}.obj'
# target_obj = f'G://obj_fix/print/{pid}/{pid}_new.obj'
# nums +=1
# print(f"当前正在处理{pid},已处理至-{nums}",)
# if str(angle[0]) == "0":
# rotate_angle = -int(angle)
# transform_obj_file(source_obj, target_obj, rotate_axis, rotate_angle)
# else:
# rotate_angle = int(angle)
# transform_obj_file(source_obj, target_obj, rotate_axis, rotate_angle)
# print(int(angle))
# print(angle,angle[0])
# # 加载模型
# mesh = o3d.io.read_triangle_mesh(target_obj, enable_post_processing=True)
# # 创建渲染窗口并添加模型
# vis = o3d.visualization.Visualizer()
# vis.create_window()
# vis.add_geometry(mesh)
# # 设置渲染参数
# render_option = vis.get_render_option()
# render_option.point_size = 1.0
# # 渲染模型
# vis.run()
# vis.destroy_window()
pid = "90864" # 98894 115123
source_obj = f'G://obj_fix/auto/{pid}/{pid}.obj'
target_obj = f'G://obj_fix/auto/{pid}/{pid}_90.obj'
#遍历文件夹下的所有文件 /data/datasets/temp/auto_preview_need_around
for file_path in list_files('G://obj_fix/auto'):
pid = file_path.split('\\')[-1].split('_')[0]
# 使用示例:
rotate_axis = (1, 0, 0) # 比如绕X轴旋转 0 x 轴
rotate_angle = -90 # 以度为单位
transform_obj_file(source_obj, target_obj, rotate_axis, rotate_angle)
# rotate_axis = (0, 1, 0) # 比如绕X轴旋转 0 x 轴
# rotate_angle = 60 # 以度为单位
# transform_obj_file(target_obj, target_obj, rotate_axis, rotate_angle)

52
script/upload_and_clear_oss.py

@ -0,0 +1,52 @@
import platform,sys,redis,time,requests,json,atexit
sys.path.append('../libs/')
import config,libs,libs_db_temp,common
import oss2,os
# 将本地文件上传到oss 中,并且清除 oss 上的文件
#文件存储lua路径
typeV = "print"
filePath = f"G://obj_fix/{typeV}"
ossPrefix = f"objs/{typeV}"
def readTask():
startTimeTask = time.time()
#读取数据库的任务
# pid = libs_db_temp.get_task_by_status(100) #2 表示该文件已经处理好了
# pid = str(pid)
pid = "4417"
if int(pid) == 0:
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: 无任务,延时10s')
time.sleep(10)
return
#检测文件是否存在
if not os.path.exists(f"{filePath}/{pid}/{pid}.obj"):
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: {pid} Error: {filePath}/{pid}/{pid}.obj does not exist.')
return False
if not os.path.exists(f"{filePath}/{pid}/{pid}Tex1.jpg"):
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: {pid} Error: {filePath}/{pid}/{pid}.obj does not exist.')
return False
if not os.path.exists(f"{filePath}/{pid}/{pid}.mtl"):
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: {pid} Error: {filePath}/{pid}/{pid}.obj does not exist.')
return False
if not os.path.exists(f"{filePath}/{pid}/{pid}_preview.png"):
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: {pid} Error: {filePath}/{pid}/{pid}.obj does not exist.')
return False
#清空oss上的文件
libs.clear_oss_by_pid(f'{ossPrefix}/{pid}')
#上传文件到oss
libs.upload_obj_to_oss(filePath,typeV,pid)
return
#程序主入口
if __name__ == '__main__':
#atexit.register(common.notify,"处理数据校准任务已经停止")
readTask()
# while True:
# pid = readTask()

259
script/url.txt

@ -0,0 +1,259 @@
https://mp.suwa3d.com/preview.html?platform=1&id=100270&size=18cm_x1&angle=1#
https://mp.suwa3d.com/preview.html?platform=1&id=104867&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=106929&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=115017&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=115028&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=115042&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=115051&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=115074&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=115123&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=115162&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=115228&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=115302&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=117004&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=119772&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=120406&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=120416&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=121495&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=121614&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=123599&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=124636&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=125097&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=125118&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=127455&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=128446&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=128719&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=13154&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=13160&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=13161&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=135850&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=136302&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=136357&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=136602&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=136603&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=136925&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=13692&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=14094&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=14148&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=14216&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=14301&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=14475&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=15012&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=15707&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=15963&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=16012&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=16074&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=16078&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=17388&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=19338&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=19405&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=20197&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=20203&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=20675&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=21007&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=21780&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=21807&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=22155&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=22159&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=22204&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=23805&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=24765&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=24766&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=24772&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=24775&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=24780&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=24784&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=25043&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=25093&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=25200&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=25568&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=26384&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=26848&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=27214&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=27534&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=27553&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=29489&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=29506&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=29507&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=29796&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=29805&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=30617&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=30624&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=30638&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=30660&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=30663&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=30705&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=30843&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=31010&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=31012&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=31442&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=31450&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=31596&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=31986&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=33899&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=36791&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=39522&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=39732&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=40613&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=40918&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=41320&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=42047&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=42595&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=42781&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=43054&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=43059&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=44322&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=44623&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=44845&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=45480&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=46352&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=47752&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=48197&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=48250&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=48477&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=48880&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=49404&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=49934&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=49935&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=50370&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=52884&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=53804&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=54701&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55011&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55021&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55030&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55075&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55076&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55081&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55082&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55083&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55084&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55090&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55092&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55114&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55367&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55370&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55372&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55730&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55844&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55849&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55860&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=55887&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=56559&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=56654&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=56750&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=56754&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=56781&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=56784&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=56797&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=56799&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=56802&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=56877&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=57168&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=57762&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=58122&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=61764&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=62516&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=63115&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=64088&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=64739&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=65653&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=65918&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=66521&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=66531&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=67655&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68349&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68688&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68692&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68699&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68700&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68718&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68724&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68730&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68735&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68807&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68821&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68906&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68916&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68925&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68926&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=68940&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=69798&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=70532&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=70729&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=70732&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=70746&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=70754&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=70756&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=70792&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=70807&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=70812&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=71318&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=71321&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=71323&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=71326&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=71356&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=71361&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=71395&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=71404&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=71407&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=71415&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=71421&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=71422&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=71701&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=74624&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=75402&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=75405&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=75408&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=75416&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=76289&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=76300&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=77221&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=77226&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=77431&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=77516&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=77957&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=77960&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=77964&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=77972&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=78376&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=78381&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=78384&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=78385&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=79263&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=79331&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=79333&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=80007&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=80166&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=80445&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=81419&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=82435&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=82440&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=82460&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=82481&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=82483&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=82486&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=82496&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=82511&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=82571&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=83698&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=83707&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=83712&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=83715&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=83727&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=83729&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=83756&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=83759&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=83761&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=83844&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=83983&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=84547&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=85652&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=86196&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=86211&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=86232&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=86252&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=87649&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=87849&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=88074&size=18cm_x1&angle=1#/
https://mp.suwa3d.com/preview.html?platform=1&id=98894&size=18cm_x1&angle=1#/

69
test.py

@ -1,60 +1,15 @@
import os, sys, time, shutil, subprocess, shlex, json import psutil
import xml.etree.ElementTree as ET
import platform
if platform.system() == 'Windows':
sys.path.append('e:\\libs\\')
#sys.path.append('libs')
else:
sys.path.append('/data/deploy/make3d/make2/libs/')
import config, libs, libs_db,common # 获取硬盘分区列表
partitions = psutil.disk_partitions()
for partition in partitions:
print("分区信息",partition)
# 获取指定分区(比如'C:')的使用情况
if partition.mountpoint == 'G:\\': # 更改为您要检测的硬盘分区
usage = psutil.disk_usage(partition.mountpoint)
if __name__ == '__main__': print(f"Total: {usage.total / (1024**3):.2f} GB")
print(f"Used: {usage.used / (1024**3):.2f} GB")
#遍历oss 指定文件夹下指定日期的文件 print(f"Free: {usage.free / (1024**3):.2f} GB")
for obj in config.bucket.list_objects(prefix="auto/"): print(f"Percentage: {usage.percent}%")
#判断是否是文件夹 并且 日期是否在 2023-11-08 之后的
if obj.key[-1] == "/" and obj.key.split("/")[1] >= "2023-11-08":
#判断是否存在这个目录
if not os.path.exists(os.path.join(config.workdir,obj.key.split("/")[1])):
os.mkdir(os.path.join(config.workdir,obj.key.split("/")[1]))
#拷贝文件到本地
for obj2 in config.bucket.list_objects(prefix=obj.key):
if obj2.key[-1] != "/":
print(obj2.key)
#判断文件是否存在
if not os.path.exists(os.path.join(config.workdir,obj2.key)):
#下载文件
config.bucket.get_object_to_file(obj2.key,os.path.join(config.workdir,obj2.key))
#判断文件是否下载成功
if os.path.exists(os.path.join(config.workdir,obj2.key)):
print("下载成功")
else:
print("下载失败")
else:
print("文件已存在")
# 解析XML文件
# pid = "112322"
# file_path = os.path.join(config.workdir, pid, f'{pid}.rcproj')
# tree = ET.parse(file_path)
# root = tree.getroot()
# # 遍历所有的reconstructions节点
# for reconstruction in root.findall('reconstructions'):
# for component in reconstruction.findall('component'):
# if component.find('model') == None:
# reconstruction.remove(component)
# continue
# # 获取所有包含model标签的component节点
# components_with_model = [component for component in reconstruction.findall('component') if component.find('model') is not None]
# print(components_with_model)
# # 如果包含model标签的component节点数量大于1,则按照model数量降序排序
# if len(components_with_model) > 1:
# components_with_model.sort(key=lambda x: len(x.findall('model')), reverse=False)
# for i in range(len(components_with_model)-1):
# reconstruction.remove(components_with_model[i])
# # 保存修改后的XML文件
# tree.write(file_path)

21
test1.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
import os
import oss2
# 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
endpoint = 'https://oss-cn-shanghai.aliyuncs.com'
# 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
access_key_id = 'LTAI5tSj7s2mKZNqamT1x64v'
access_key_secret = 'iIqeBLB8R2U72pAwJbZZBB6tuB3ZF9'
# 指定文件所在的Bucket名称,例如examplebucket。
bucket_name = 'suwa3d-securedata'
# Object完整路径,完整路径中不能包含Bucket名称。
key = 'photos/141640/photo2/72_8.jpg'
# 指定Bucket实例,所有文件相关的方法都需要通过Bucket实例来调用。
bucket = oss2.Bucket(oss2.Auth(access_key_id, access_key_secret), endpoint, bucket_name)
style = 'image/bodies'
# 生成带签名的URL,并指定过期时间为10分钟。过期时间单位为秒。
url = bucket.sign_url('GET', key, 10 * 60, params={'x-oss-process': style})
print(url)

124
tools/test.py

@ -0,0 +1,124 @@
import open3d as o3d
from open3d.visualization.gui import Application
from open3d.visualization import O3DVisualizer
import sys, os
# 假设 obj_file_path 是你的 OBJ 文件路径,image_save_path 是保存图片的路径
filePath = "G://obj_fix/print"
pid = "8160"
obj_file_path = f"{filePath}/{pid}/{pid}.obj"
image_save_path = f"{filePath}/{pid}/{pid}_test.png"
# import open3d as o3d
# 加载OBJ文件
mesh = o3d.io.read_triangle_mesh(obj_file_path)
# 创建一个OffscreenRenderer对象
renderer = o3d.visualization.rendering.OffscreenRenderer()
# 创建一个Open3DScene对象
scene = o3d.visualization.rendering.Open3DScene()
# 将几何体添加到场景中
scene.add_geometry(mesh)
# 创建一个材质并应用到几何体上
material = o3d.visualization.rendering.MaterialRecord()
material.base_color = [1.0, 1.0, 1.0] # 白色材质
mesh.materials.append(material)
# 创建一个灯光对象
light = o3d.visualization.rendering.Light()
light.type = "directional" # 方向光
light.direction = [0.0, -1.0, 0.0] # 光照方向
light.color = [1.0, 1.0, 1.0] # 白色光线
# 将灯光添加到场景中
scene.add_light(light)
# 设置渲染参数
renderer.set_scene(scene)
# 渲染场景
image = renderer.render()
# 显示渲染结果
o3d.geometry.image.axial_slice(image, 2, (128, 128, 128))
# # 计算顶点法线,这对于渲染是非常重要的
# mesh.compute_vertex_normals()
# # 可选:可以对网格进行进一步处理,例如滤波或下采样
# # mesh = o3d.geometry.filter_triangle_mesh(mesh, "default")
# # 创建一个Open3D的可视化对象
# vis = o3d.visualization.Visualizer()
# vis.create_window()
# # 将网格添加到可视化对象中
# vis.add_geometry(mesh)
# # 创建一个环境光源
# light = get_light_source("default")
# light.set_intensity([1.0, 1.0, 1.0]) # 设置光照强度
# # 将灯光添加到可视化对象中
# vis.add_light(light)
# # 调整灯光位置和方向
# light.set_position([0.0, 0.0, 0.0])
# light.set_direction([0.0, 0.0, 1.0])
# screenshot = vis.capture_screen()
# o3d.io.write_image("screenshot.png", screenshot)
# # 渲染并显示窗口
# vis.run()
# # 加载一个点云或者网格
# mesh = o3d.io.read_triangle_mesh(obj_file_path)
# # 创建 O3DVisualizer 实例
# vis = o3d.visualization.O3DVisualizer("O3D Visualizer Example", 1024, 768)
# # 添加几何体到可视化窗口
# vis.add_geometry("Mesh", mesh)
# # 显示可视化窗口
# Application.instance.add_window(vis)
# Application.instance.run()
# # Derive the object path set the model, material, and shader
# model_dir = sys.argv[1]
# model_name = os.path.join(model_dir, os.path.basename(model_dir) + ".obj")
# model = o3d.io.read_triangle_mesh(obj_file_path)
# material = o3d.visualization.rendering.Material()
# material.shader = "defaultLit"
# # Derive the texture paths
# albedo_name = os.path.join(model_dir, "albedo.png")
# normal_name = os.path.join(model_dir, "normal.png")
# ao_name = os.path.join(model_dir, "ao.png")
# metallic_name = os.path.join(model_dir, "metallic.png")
# roughness_name = os.path.join(model_dir, "roughness.png")
# # Check if the textures are available and loads the texture. For example, if metallic exists then load metallic texture
# if os.path.exists(albedo_name):
# material.albedo_img = o3d.io.read_image(albedo_name)
# if os.path.exists(normal_name):
# material.normal_img = o3d.io.read_image(normal_name)
# if os.path.exists(ao_name):
# material.ao_img = o3d.io.read_image(ao_name)
# if os.path.exists(metallic_name):
# material.base_metallic = 1.0
# material.metallic_img = o3d.io.read_image(metallic_name)
# if os.path.exists(roughness_name):
# material.roughness_img = o3d.io.read_image(roughness_name)
# # Draw an object named cube using the available model and texture
# o3d.visualization.draw([{"name": "cube", "geometry": model, "material": material}])
Loading…
Cancel
Save