程序优化
This commit is contained in:
1 parent
e83deda268
commit
e1a7647fcb
16 files changed
+634
-91
No files matched your search
@@ -0,0 +1,14 @@
|
|||||||
|
<Configuration id="{2D5793BC-A65D-4318-A1B9-A05044608385}">
|
||||||
|
<entry key="MvsExportIsGeoreferenced" value="0x0"/>
|
||||||
|
<entry key="MvsExportMoveX" value="0.0"/>
|
||||||
|
<entry key="MvsExportMoveY" value="0.0"/>
|
||||||
|
<entry key="MvsExportMoveZ" value="0.0"/>
|
||||||
|
<entry key="MvsExportScaleX" value="1.0"/>
|
||||||
|
<entry key="calexFileFormat" value="Internal/External camera parameters"/>
|
||||||
|
<entry key="calexExportSettingsVisible" value="1"/>
|
||||||
|
<entry key="MvsExportScaleY" value="1.0"/>
|
||||||
|
<entry key="calexHasDisabled" value="0x0"/>
|
||||||
|
<entry key="MvsExportScaleZ" value="1.0"/>
|
||||||
|
<entry key="calexHasUndistort" value="0x0"/>
|
||||||
|
<entry key="MvsExportIsModelCoordinates" value="0"/>
|
||||||
|
</Configuration>
|
||||||
+163
-8
@@ -1,5 +1,8 @@
|
|||||||
import redis,sys,os,re,oss2,shutil,time
|
import redis,sys,os,re,oss2,shutil,time,cv2
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
import platform
|
import platform
|
||||||
|
import numpy as np
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from PIL import ImageGrab
|
from PIL import ImageGrab
|
||||||
if platform.system() == 'Windows':
|
if platform.system() == 'Windows':
|
||||||
@@ -222,14 +225,14 @@ def uploadControlPointsOss(pid):
|
|||||||
#截屏保存
|
#截屏保存
|
||||||
def saveScreenImg(pid):
|
def saveScreenImg(pid):
|
||||||
#获取当前的日志
|
#获取当前的日志
|
||||||
if not os.path.exists(os.path.join(config.workdir,"screen", time.strftime("%y%m%d" time.localtime()))):
|
if not os.path.exists(os.path.join(config.workdir,"screen", time.strftime("%y%m%d",time.localtime()))):
|
||||||
os.makedirs(os.path.join(config.workdir,"screen", time.strftime("%y%m%d" time.localtime())))
|
os.makedirs(os.path.join(config.workdir,"screen", time.strftime("%y%m%d",time.localtime())))
|
||||||
screenshot = ImageGrab .grab()
|
screenshot = ImageGrab .grab()
|
||||||
screenshot.save(os.path.join(config.workdir,"screen", time.strftime("%y%m%d" time.localtime())),str(pid)+".png")
|
screenshot.save(os.path.join(config.workdir,"screen", time.strftime("%y%m%d",time.localtime()))+"/"+str(pid)+".png")
|
||||||
#移动到e盘
|
#移动到e盘
|
||||||
if not os.path.exists(os.path.join(config.sharedir,"screen", time.strftime("%y%m%d" time.localtime()))):
|
if not os.path.exists(os.path.join(config.sharedir,"screen", time.strftime("%y%m%d",time.localtime()))):
|
||||||
os.makedirs(os.path.join(config.sharedir,"screen", time.strftime("%y%m%d" time.localtime())))
|
os.makedirs(os.path.join(config.sharedir,"screen", time.strftime("%y%m%d",time.localtime())))
|
||||||
shutil.copytree(os.path.join(config.workdir,"screen", time.strftime("%y%m%d" time.localtime())), os.path.join(config.sharedir,"screen", time.strftime("%y%m%d" time.localtime())))
|
shutil.copy(os.path.join(config.workdir,"screen", time.strftime("%y%m%d",time.localtime()))+"\\"+str(pid)+".png", os.path.join(config.sharedir,"screen", time.strftime("%y%m%d",time.localtime())))
|
||||||
|
|
||||||
|
|
||||||
#文件夹的移动和删除
|
#文件夹的移动和删除
|
||||||
@@ -247,4 +250,156 @@ def removeFolder(pid):
|
|||||||
file_time = os.path.getmtime(os.path.join(config.workdir, 'finished', file))
|
file_time = os.path.getmtime(os.path.join(config.workdir, 'finished', file))
|
||||||
now_time = time.time()
|
now_time = time.time()
|
||||||
if (now_time - file_time) > 259200:
|
if (now_time - file_time) > 259200:
|
||||||
shutil.rmtree(os.path.join(config.workdir, 'finished', file), ignore_errors=True)
|
shutil.rmtree(os.path.join(config.workdir, 'finished', file), ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
|
def find_last_x(image, slope_threshold = 1000):
|
||||||
|
x = []
|
||||||
|
y = []
|
||||||
|
hist, bins = np.histogram(image, bins=256, range=[0, 256])
|
||||||
|
|
||||||
|
#找到50以内的最高峰
|
||||||
|
max_y = 0
|
||||||
|
max_i = 5
|
||||||
|
for i in range(5, 50):
|
||||||
|
if hist[i] > max_y:
|
||||||
|
max_y = hist[i]
|
||||||
|
max_i = i
|
||||||
|
print(f'50以内最高峰值y:{max_y},最高峰位置x:{max_i}')
|
||||||
|
|
||||||
|
for i in range(2, max_i):
|
||||||
|
x.append(i)
|
||||||
|
y.append(hist[i])
|
||||||
|
slopes = [abs(y[i + 1] - y[i]) for i in range(len(x) - 1)]
|
||||||
|
|
||||||
|
current_interval = []
|
||||||
|
max_interval = []
|
||||||
|
max_x = {}
|
||||||
|
for i, slope in enumerate(slopes):
|
||||||
|
current_interval.append(slope)
|
||||||
|
if slope >= slope_threshold:
|
||||||
|
if len(current_interval) > len(max_interval):
|
||||||
|
max_interval = current_interval.copy()
|
||||||
|
max_x[x[i]] = slope
|
||||||
|
current_interval = []
|
||||||
|
|
||||||
|
print(max_x)
|
||||||
|
last_x = list(max_x)[-1]
|
||||||
|
last_y = max_x[last_x]
|
||||||
|
return last_x, last_y
|
||||||
|
|
||||||
|
def high_find_histogram_range(image, target_frequency):
|
||||||
|
'''
|
||||||
|
循环查找在 target_frequency (y)频次限制下的直方图区间值(x)
|
||||||
|
:param image: 导入图片
|
||||||
|
:param target_frequency: 直方图 y 频次限制条件
|
||||||
|
:return: 直方图区间 x,和 该区间频次 y
|
||||||
|
'''
|
||||||
|
# 计算灰度直方图
|
||||||
|
hist, bins = np.histogram(image, bins=256, range=[0, 256])
|
||||||
|
# 初始化区间和频次
|
||||||
|
interval = 255
|
||||||
|
frequency = hist[255]
|
||||||
|
while frequency < target_frequency:
|
||||||
|
# 更新区间和频次
|
||||||
|
interval -= 1
|
||||||
|
# 检查直方图的频次是否为None,如果频次是None,则将其设为0,这样可以避免将None和int进行比较报错。
|
||||||
|
frequency = hist[interval] if hist[interval] is not None else 0
|
||||||
|
frequency += hist[interval] if hist[interval] is not None else 0
|
||||||
|
# 如果频次接近10000则停止循环
|
||||||
|
if target_frequency - 2000 <= frequency <= target_frequency + 2000:
|
||||||
|
break
|
||||||
|
|
||||||
|
return interval, frequency
|
||||||
|
|
||||||
|
def ps_color_scale_adjustment(image, shadow=0, highlight=255, midtones=1):
|
||||||
|
'''
|
||||||
|
模拟 PS 的色阶调整; 0 <= Shadow < Highlight <= 255
|
||||||
|
:param image: 传入的图片
|
||||||
|
:param shadow: 黑场(0-Highlight)
|
||||||
|
:param highlight: 白场(Shadow-255)
|
||||||
|
:param midtones: 灰场(9.99-0.01)
|
||||||
|
:return: 图片
|
||||||
|
'''
|
||||||
|
if highlight > 255:
|
||||||
|
highlight = 255
|
||||||
|
if shadow < 0:
|
||||||
|
shadow = 0
|
||||||
|
if shadow >= highlight:
|
||||||
|
shadow = highlight - 2
|
||||||
|
if midtones > 9.99:
|
||||||
|
midtones = 9.99
|
||||||
|
if midtones < 0.01:
|
||||||
|
midtones = 0.01
|
||||||
|
image = np.array(image, dtype=np.float16)
|
||||||
|
# 计算白场 黑场离差
|
||||||
|
Diff = highlight - shadow
|
||||||
|
image = image - shadow
|
||||||
|
image[image < 0] = 0
|
||||||
|
image = (image / Diff) ** (1 / midtones) * 255
|
||||||
|
image[image > 255] = 255
|
||||||
|
image = np.array(image, dtype=np.uint8)
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def remove_gray_and_sharpening(jpg_path):
|
||||||
|
#low_y_limit = 25000
|
||||||
|
high_y_limit = 13000
|
||||||
|
input_image = cv2.imread(jpg_path)
|
||||||
|
# low_x_thresh, low_y_frequency = low_find_histogram_range(input_image, low_y_limit)
|
||||||
|
low_x_thresh, low_y_frequency = find_last_x(input_image, 1000)
|
||||||
|
high_x_thresh, high_y_frequency = high_find_histogram_range(input_image, high_y_limit)
|
||||||
|
print(f"{low_x_thresh} 区间, {low_y_frequency} 频次")
|
||||||
|
print(f"{high_x_thresh} 区间, {high_y_frequency} 频次")
|
||||||
|
high_output_image = ps_color_scale_adjustment(input_image, shadow=low_x_thresh, highlight=high_x_thresh, midtones=1)
|
||||||
|
cv2.imwrite(jpg_path, high_output_image, [cv2.IMWRITE_JPEG_QUALITY, 95]) # 保存图片的质量是原图的 95%
|
||||||
|
|
||||||
|
#读取指定路径判断是否对齐成功
|
||||||
|
def isAlignNums(strPid):
|
||||||
|
#拼接路径
|
||||||
|
csvPath = os.path.join(config.workdir, strPid, strPid+"_align.csv")
|
||||||
|
print(csvPath)
|
||||||
|
#判断文件是否存在
|
||||||
|
if os.path.exists(csvPath) == False:
|
||||||
|
return "rebuild"
|
||||||
|
#读取文件行数
|
||||||
|
lines = ""
|
||||||
|
with open(csvPath, 'r') as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
#获取长度
|
||||||
|
lines = len(lines) - 1
|
||||||
|
#获取pid对应的 photo1 和 photo2 的数量
|
||||||
|
photo1Num = 0
|
||||||
|
photo2Num = 0
|
||||||
|
for file in os.listdir(os.path.join(config.workdir, strPid, 'photo1')):
|
||||||
|
if file.endswith('.jpg'):
|
||||||
|
photo1Num += 1
|
||||||
|
|
||||||
|
for file in os.listdir(os.path.join(config.workdir, strPid, 'photo2')):
|
||||||
|
if file.endswith('.jpg'):
|
||||||
|
photo2Num += 1
|
||||||
|
#获取图片总数
|
||||||
|
totalPhotos = photo1Num + photo2Num
|
||||||
|
#比对对齐数量
|
||||||
|
if totalPhotos - lines >= 4:
|
||||||
|
return "rebuild"
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
#消息通知
|
||||||
|
def notify(content):
|
||||||
|
|
||||||
|
if content == "":
|
||||||
|
return "content 不能为空"
|
||||||
|
|
||||||
|
for user_agent_id in config.notify_user_Ids:
|
||||||
|
data = {
|
||||||
|
'userId': user_agent_id,
|
||||||
|
'message': content,
|
||||||
|
}
|
||||||
|
headers = {'Content-Type': 'application/json'}
|
||||||
|
message_send_url = "https://mp.api.suwa3d.com/api/qyNotify/sendMessage?userId="+user_agent_id+"&message="+content
|
||||||
|
response = requests.post(message_send_url, data=json.dumps(data), headers=headers)
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
import bpy
|
||||||
|
import bmesh
|
||||||
|
|
||||||
|
|
||||||
|
def active_object(obj):
|
||||||
|
bpy.context.view_layer.objects.active = obj
|
||||||
|
obj.select_set(True)
|
||||||
|
|
||||||
|
|
||||||
|
def get_obj_max_foot(workdir,filename,filename_tex):
|
||||||
|
# 1.模型导入和初始化
|
||||||
|
# 删除当前场景中的所有对象:
|
||||||
|
# use_global=False表示只删除当前场景中的对象,而不会影响到其他场景中的对象;confirm=False表示删除时不需要确认。
|
||||||
|
bpy.ops.object.delete(use_global=False, confirm=False)
|
||||||
|
bpy.ops.import_scene.obj(filepath=filename) # 导入指定路径的 OBJ 格式模型文件
|
||||||
|
|
||||||
|
bpy.context.scene.unit_settings.scale_length = 0.001 # 将场景的长度单位缩放为0.001,相当于将长度单位从默认的米缩小为毫米
|
||||||
|
bpy.context.scene.unit_settings.length_unit = 'CENTIMETERS' # 将场景的长度单位设置为厘米
|
||||||
|
bpy.context.scene.unit_settings.mass_unit = 'GRAMS' # 将场景的质量单位设置为克
|
||||||
|
|
||||||
|
obj = bpy.context.selected_objects[0] # 获取了当前选中的对象列表,然后通过 [0] 取得列表中的第一个对象
|
||||||
|
bpy.context.view_layer.objects.active = obj # 将变量 obj 设置为当前活动对象
|
||||||
|
obj.select_set(True) # 将变量 obj 的选择状态设置为 True,表示选中该对象
|
||||||
|
pid = obj.name # 获取该对象的名字
|
||||||
|
|
||||||
|
# 对选定的对象进行对齐操作
|
||||||
|
bpy.ops.object.align(align_mode='OPT_1', relative_to='OPT_1', align_axis={'Z'})
|
||||||
|
# 设置选中对象的原点,参数1:将原点设置为对象的质心,参数2:使用对象的几何中心作为参考
|
||||||
|
bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS', center='MEDIAN')
|
||||||
|
# 将选中对象的位置坐标分别设置为 (0, 0),即将对象移动到世界坐标系的原点位置
|
||||||
|
obj.location[0] = 0
|
||||||
|
obj.location[1] = 0
|
||||||
|
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) # 将选中对象的位置、旋转和缩放应用到对象的数据中
|
||||||
|
|
||||||
|
# 2.选择要复制的对象
|
||||||
|
obj_duplicate = obj.copy()
|
||||||
|
obj_duplicate.data = obj.data.copy()
|
||||||
|
bpy.context.collection.objects.link(obj_duplicate)
|
||||||
|
# obj_duplicate.location.x += 5.0
|
||||||
|
bpy.ops.object.select_all(action='DESELECT') # 取消选中全部对象
|
||||||
|
|
||||||
|
# 3.处理复制的对象的脚底缝合边
|
||||||
|
# 选中复制对象
|
||||||
|
bpy.context.view_layer.objects.active = obj_duplicate
|
||||||
|
obj_duplicate.select_set(True)
|
||||||
|
|
||||||
|
selected_obj = bpy.context.active_object # 获取当前选中的对象
|
||||||
|
bpy.context.view_layer.objects.active = selected_obj # 将对象转换到编辑模式
|
||||||
|
|
||||||
|
# 切换到3D视图编辑模式
|
||||||
|
bpy.context.area.type = 'VIEW_3D'
|
||||||
|
bpy.ops.object.mode_set(mode='EDIT')
|
||||||
|
bpy.ops.mesh.select_all(action='SELECT') # 选择所有的边
|
||||||
|
|
||||||
|
# 切换到UV编辑器
|
||||||
|
bpy.context.area.type = 'IMAGE_EDITOR'
|
||||||
|
pid_img = f"{pid}Tex1.jpg"
|
||||||
|
bpy.ops.image.open(filepath=filename_tex, directory=workdir,
|
||||||
|
files=[{"name": pid_img, "name": pid_img}], relative_path=True,
|
||||||
|
show_multiview=False)
|
||||||
|
bpy.context.area.ui_type = 'UV'
|
||||||
|
bpy.ops.uv.select_all(action='SELECT') # 选择所有UV贴图顶点
|
||||||
|
# 标记所有沿孤岛的边为缝合边
|
||||||
|
bpy.ops.uv.seams_from_islands()
|
||||||
|
bpy.context.area.type = 'VIEW_3D'
|
||||||
|
bpy.ops.object.mode_set(mode='OBJECT')
|
||||||
|
|
||||||
|
# 获取世界坐标系下z轴接近0的顶点的索引
|
||||||
|
z_zero_vertex_indices = []
|
||||||
|
for i, vertex in enumerate(selected_obj.data.vertices):
|
||||||
|
world_vertex = selected_obj.matrix_world @ vertex.co
|
||||||
|
if abs(world_vertex.z) < 0.2:
|
||||||
|
z_zero_vertex_indices.append(i)
|
||||||
|
# 将对象转换回对象模式
|
||||||
|
bpy.ops.object.mode_set(mode='OBJECT')
|
||||||
|
# 创建一个新的顶点组,并将z_zero_vertices中的顶点添加到该顶点组中
|
||||||
|
vg = selected_obj.vertex_groups.new(name="z_zero_vertices")
|
||||||
|
for index in z_zero_vertex_indices:
|
||||||
|
vg.add([index], 1.0, 'REPLACE')
|
||||||
|
# 将选中的顶点设置为活动顶点
|
||||||
|
bpy.ops.object.mode_set(mode='EDIT')
|
||||||
|
bpy.ops.mesh.select_all(action='DESELECT')
|
||||||
|
bpy.ops.object.vertex_group_select() # 选中待处理的顶点
|
||||||
|
bpy.ops.mesh.mark_seam(clear=True) # 取消所选区域内的缝合边
|
||||||
|
bpy.ops.mesh.region_to_loop() # 选择选定面周围的边界边!!!
|
||||||
|
bpy.ops.mesh.select_mode(type="EDGE") # 转换为线模式
|
||||||
|
bpy.ops.mesh.mark_seam(clear=False) # 标记所选的线为缝合边
|
||||||
|
|
||||||
|
# 选中脚底顶点组
|
||||||
|
bpy.ops.uv.select_all(action='DESELECT')
|
||||||
|
bpy.ops.object.vertex_group_set_active(group='z_zero_vertices') # 设置活动顶点组
|
||||||
|
bpy.ops.object.vertex_group_select() # 选择分配给活动顶点组的所有顶点
|
||||||
|
bpy.ops.uv.unwrap()
|
||||||
|
|
||||||
|
# 处理贴图脚底部分孤岛,其他孤岛保持不变
|
||||||
|
# (1)反选模型顶点,方便贴图固定不需要处理的区域
|
||||||
|
bpy.ops.mesh.select_all(action='INVERT')
|
||||||
|
bpy.context.area.type = 'IMAGE_EDITOR' # 切换到贴图模式
|
||||||
|
bpy.context.area.ui_type = 'UV'
|
||||||
|
bpy.ops.uv.pin(clear=False)
|
||||||
|
bpy.ops.object.vertex_group_set_active(group='z_zero_vertices') # 设置活动顶点组
|
||||||
|
bpy.ops.object.vertex_group_select() # 选择分配给活动顶点组的所有顶点
|
||||||
|
# (2)脚底部位UV展开,平均孤岛比例,重新排列孤岛
|
||||||
|
bpy.ops.uv.select_all(action='SELECT')
|
||||||
|
bpy.ops.uv.average_islands_scale()
|
||||||
|
bpy.ops.uv.pack_islands(margin=0.001)
|
||||||
|
|
||||||
|
bpy.context.area.type = 'VIEW_3D'
|
||||||
|
bpy.ops.object.mode_set(mode='OBJECT')
|
||||||
|
|
||||||
|
# 4. 烘焙模式,参数设置
|
||||||
|
bpy.ops.object.select_all(action='DESELECT') # 取消选中全部对象
|
||||||
|
# # 选中原始对象
|
||||||
|
bpy.context.view_layer.objects.active = obj
|
||||||
|
obj.select_set(True)
|
||||||
|
# 选中复制对象
|
||||||
|
bpy.context.view_layer.objects.active = obj_duplicate
|
||||||
|
obj_duplicate.select_set(True)
|
||||||
|
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_selected_to_active = True
|
||||||
|
bpy.context.scene.render.bake.cage_extrusion = 0.01
|
||||||
|
bpy.ops.object.bake(type='DIFFUSE') # 开始 Bake
|
||||||
|
|
||||||
|
# 5. 导出模型和贴图
|
||||||
|
bpy.ops.object.select_all(action='DESELECT') # 取消选中全部对象
|
||||||
|
# 选中复制对象
|
||||||
|
bpy.context.view_layer.objects.active = obj_duplicate
|
||||||
|
obj_duplicate.select_set(True)
|
||||||
|
bpy.ops.wm.obj_export(filepath=filename, export_selected_objects=True)
|
||||||
|
bpy.context.area.type = 'IMAGE_EDITOR' # 切换到
|
||||||
|
bpy.ops.image.save_as(filepath=filename_tex)
|
||||||
|
bpy.context.area.type = 'TEXT_EDITOR' # 切换到文本编辑器
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
workdir = 'E:\\117080\\print_model'
|
||||||
|
# filename = f'{workdir}\\117080_12cm_x1.obj'
|
||||||
|
filename = f'{workdir}\\117080.obj'
|
||||||
|
filename_tex = f'{workdir}\\117080Tex1.jpg'
|
||||||
|
save_obj = f"{workdir}\\bake\\117080Tex1.obj"
|
||||||
|
save_tex = f"{workdir}\\bake\\117080Tex1.jpg"
|
||||||
|
|
||||||
|
get_obj_max_foot()
|
||||||
+40
-6
@@ -1,7 +1,9 @@
|
|||||||
import os, time, json, requests, shutil, oss2, psutil
|
import os, time, json, requests, shutil, oss2, psutil
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
from PIL import Image, ImageEnhance
|
from PIL import Image, ImageEnhance
|
||||||
import config,libs_db
|
import config,libs_db,common
|
||||||
|
import threading
|
||||||
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
|
||||||
def find_blender_bin_path():
|
def find_blender_bin_path():
|
||||||
base_path = 'C:\\Program Files\\Blender Foundation\\'
|
base_path = 'C:\\Program Files\\Blender Foundation\\'
|
||||||
@@ -222,7 +224,7 @@ def set_photo_join_type(workdir, pid, photoN, camera_id, mesh = '0', texture='0'
|
|||||||
with open(filename, 'w') as f:
|
with open(filename, 'w') as f:
|
||||||
f.writelines(lines)
|
f.writelines(lines)
|
||||||
|
|
||||||
def down_from_oss(oss_client, workdir, pid, per=100):
|
def down_from_oss(oss_client, workdir, pid, per=100,photoPath=""):
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
path = os.path.join(workdir, pid)
|
path = os.path.join(workdir, pid)
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
@@ -237,20 +239,52 @@ def down_from_oss(oss_client, workdir, pid, per=100):
|
|||||||
filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix)
|
filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix)
|
||||||
for file in tqdm(filelist):
|
for file in tqdm(filelist):
|
||||||
filename = file.key.split('/')[-1]
|
filename = file.key.split('/')[-1]
|
||||||
|
localfile = ""
|
||||||
# print('正在下载:', file.key)
|
# print('正在下载:', file.key)
|
||||||
if filename.endswith('_1.jpg'):
|
if photoPath == "":
|
||||||
localfile = os.path.join(path, 'photo1', filename)
|
if filename.endswith('_1.jpg'):
|
||||||
|
localfile = os.path.join(path, 'photo1', filename)
|
||||||
|
else:
|
||||||
|
localfile = os.path.join(path, 'photo2', filename)
|
||||||
else:
|
else:
|
||||||
localfile = os.path.join(path, 'photo2', filename)
|
if photoPath=="1":
|
||||||
|
if filename.endswith('_1.jpg'):
|
||||||
|
localfile = os.path.join(path, 'photo1', filename)
|
||||||
|
else:
|
||||||
|
if filename.endswith('_8.jpg'):
|
||||||
|
localfile = os.path.join(path, 'photo2', filename)
|
||||||
|
if localfile == "":
|
||||||
|
continue
|
||||||
style = f'image/resize,p_{per}'
|
style = f'image/resize,p_{per}'
|
||||||
if per == 100:
|
if per == 100:
|
||||||
oss_client.get_object_to_file(file.key, localfile)
|
oss_client.get_object_to_file(file.key, localfile)
|
||||||
else:
|
else:
|
||||||
oss_client.get_object_to_file(file.key, localfile, process=style)
|
oss_client.get_object_to_file(file.key, localfile, process=style)
|
||||||
|
|
||||||
|
#判断localfile 是否有包含 photo2
|
||||||
|
|
||||||
|
|
||||||
|
#遍历处理photo2的数数据
|
||||||
|
# if str(psid) == "96" or str(pid) == "118994":
|
||||||
|
# path = os.path.join(workdir, pid, 'photo2')
|
||||||
|
# files = []
|
||||||
|
# for fileName in os.listdir(path):
|
||||||
|
# if ".jpg" in fileName:
|
||||||
|
# files.append(path+"\\"+fileName)
|
||||||
|
# beginTime = time.time()
|
||||||
|
# with ThreadPoolExecutor(max_workers=6) as executor:
|
||||||
|
# executor.map(process_image, files)
|
||||||
|
|
||||||
|
# print(f'{localfile}灰度处理费时{diff_time(beginTime)}')
|
||||||
|
|
||||||
|
|
||||||
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 图片下载完成, 共费时{diff_time(start_time)}')
|
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 图片下载完成, 共费时{diff_time(start_time)}')
|
||||||
|
|
||||||
|
#灰度处理图片
|
||||||
|
def process_image(localfile):
|
||||||
|
if ".jpg" in localfile:
|
||||||
|
common.remove_gray_and_sharpening(localfile)
|
||||||
|
|
||||||
def get_defineDistances(psid):
|
def get_defineDistances(psid):
|
||||||
res = ''
|
res = ''
|
||||||
distances = libs_db.get_floor_sticker_distances(psid).split(';')
|
distances = libs_db.get_floor_sticker_distances(psid).split(';')
|
||||||
|
|||||||
+22
-4
@@ -17,8 +17,7 @@ def get_task(task_type):
|
|||||||
try:
|
try:
|
||||||
with pymysqlAlias() as conn:
|
with pymysqlAlias() as conn:
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
sql = f'select task_key from tasks where status = 0 order by priority desc, id asc limit 1 for update'
|
||||||
sql = f'select task_key from tasks where status = 0 order by priority desc, id asc limit 1'
|
|
||||||
# print(f'sql: {sql}')
|
# print(f'sql: {sql}')
|
||||||
cursor.execute(sql)
|
cursor.execute(sql)
|
||||||
data = cursor.fetchone()
|
data = cursor.fetchone()
|
||||||
@@ -49,6 +48,9 @@ def add_task(data):
|
|||||||
|
|
||||||
#新增任务到分布式处理任务表中 {"task_type":key,"task_key":pid,"psid":psid}
|
#新增任务到分布式处理任务表中 {"task_type":key,"task_key":pid,"psid":psid}
|
||||||
def add_task_distributed(data):
|
def add_task_distributed(data):
|
||||||
|
flag = isInTaskDistributed(data["task_key"])
|
||||||
|
if flag:
|
||||||
|
return "already"
|
||||||
try:
|
try:
|
||||||
with pymysqlAlias() as conn:
|
with pymysqlAlias() as conn:
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
@@ -66,8 +68,8 @@ def start_task(data):
|
|||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
||||||
hostname = socket.gethostname()
|
hostname = socket.gethostname()
|
||||||
sql = f'update tasks set status = 1, hostname = "{hostname}", started_at = now(), updated_at = now() where task_key = "{data["task_key"]} and status = 0"'
|
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}')
|
print(f'开始任务sql: {sql}')
|
||||||
cursor.execute(sql)
|
cursor.execute(sql)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -158,4 +160,20 @@ def isStudioConfigDistribute(psid):
|
|||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())} 执行change_to_new_make_psid()异常: {str(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"
|
return "error"
|
||||||
@@ -192,10 +192,7 @@ def get_task_distributed_step1():
|
|||||||
try:
|
try:
|
||||||
with pymysqlAlias() as conn:
|
with pymysqlAlias() as conn:
|
||||||
cursor = conn.cursor(pymysql.cursors.DictCursor)
|
cursor = conn.cursor(pymysql.cursors.DictCursor)
|
||||||
sql = 'select * from task_distributed where status =0 order by priority desc limit 1'
|
sql = 'select * from task_distributed where status =0 order by priority desc limit 1 for update'
|
||||||
if where:
|
|
||||||
sql += f' and {where}'
|
|
||||||
|
|
||||||
cursor.execute(sql)
|
cursor.execute(sql)
|
||||||
result = cursor.fetchone()
|
result = cursor.fetchone()
|
||||||
# 关闭游标和连接
|
# 关闭游标和连接
|
||||||
|
|||||||
@@ -43,9 +43,10 @@ def get_task_distributed():
|
|||||||
return 'no_data'
|
return 'no_data'
|
||||||
else:
|
else:
|
||||||
#优先处理step1 和 step3
|
#优先处理step1 和 step3
|
||||||
|
resultData = main_service_db.get_task_distributed_step1()
|
||||||
#R11 R12的主机如果已经有在处理step2了,则不能再处理step2,只能处理step1 step3
|
#R11 R12的主机如果已经有在处理step2了,则不能再处理step2,只能处理step1 step3
|
||||||
resultData = need_run_step_no_step2()
|
#resultData = need_run_step_no_step2()
|
||||||
if resultData == "no":
|
if resultData is None:
|
||||||
#return "no"
|
#return "no"
|
||||||
#R11 R12的主机 可以执行step1 2 3 的任务
|
#R11 R12的主机 可以执行step1 2 3 的任务
|
||||||
#如果R11 R12的主机目前没有正在执行step2,则优先处理step2,
|
#如果R11 R12的主机目前没有正在执行step2,则优先处理step2,
|
||||||
@@ -62,8 +63,9 @@ def get_task_distributed():
|
|||||||
return resultData
|
return resultData
|
||||||
#没有任何可执行的
|
#没有任何可执行的
|
||||||
return "no"
|
return "no"
|
||||||
|
|
||||||
resultData["hostname"] = hostname
|
resultData = {"hostname":hostname,"run_step":"step1","task_distributed_id":resultData["id"],"task_key":resultData["task_key"]}
|
||||||
|
#resultData["hostname"] = hostname
|
||||||
flagRes = update_main_and_add_detail(resultData)
|
flagRes = update_main_and_add_detail(resultData)
|
||||||
if flagRes == "error":
|
if flagRes == "error":
|
||||||
print(f'出现错误,有可能是多个进程获取同一个任务了')
|
print(f'出现错误,有可能是多个进程获取同一个任务了')
|
||||||
@@ -213,8 +215,8 @@ def need_run_step_no_step1():
|
|||||||
xstep = need_run_stepx(row["id"])
|
xstep = need_run_stepx(row["id"])
|
||||||
#print("查询非step1的任务列表",xstep,row["id"])
|
#print("查询非step1的任务列表",xstep,row["id"])
|
||||||
if xstep == "step2":
|
if xstep == "step2":
|
||||||
if common.task_need_high_model_or_photo3(row["task_key"]) and hostname != "R11" and hostname != "R12":
|
# if common.task_need_high_model_or_photo3(row["task_key"]) and hostname != "R11" and hostname != "R12":
|
||||||
continue
|
# continue
|
||||||
#没有正在执行的step1,则返回该任务
|
#没有正在执行的step1,则返回该任务
|
||||||
return {"hostname":hostname,"run_step":xstep,"task_distributed_id":row["id"],"task_key":row["task_key"]}
|
return {"hostname":hostname,"run_step":xstep,"task_distributed_id":row["id"],"task_key":row["task_key"]}
|
||||||
return "no"
|
return "no"
|
||||||
|
|||||||
+3
-2
@@ -1,6 +1,6 @@
|
|||||||
import sys,socket,time,platform
|
import sys,socket,time,platform
|
||||||
from logic import logic_main_service
|
from logic import logic_main_service
|
||||||
import logging
|
import logging,atexit
|
||||||
import main_step1,main_step2,main_step3
|
import main_step1,main_step2,main_step3
|
||||||
if platform.system() == 'Windows':
|
if platform.system() == 'Windows':
|
||||||
#线上正式运行
|
#线上正式运行
|
||||||
@@ -8,8 +8,9 @@ if platform.system() == 'Windows':
|
|||||||
#本地测试
|
#本地测试
|
||||||
else:
|
else:
|
||||||
sys.path.append('/data/deploy/make3d/make2/libs/')
|
sys.path.append('/data/deploy/make3d/make2/libs/')
|
||||||
import main_service_db,config
|
import main_service_db,config,common
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
atexit.register(common.notify,socket.gethostname()+"分布式建模任务已经停止")
|
||||||
if len(sys.argv) == 2:
|
if len(sys.argv) == 2:
|
||||||
print(sys.argv[1])
|
print(sys.argv[1])
|
||||||
os.system(f'python main_step1.py {sys.argv[1]}')
|
os.system(f'python main_step1.py {sys.argv[1]}')
|
||||||
|
|||||||
+3
-2
@@ -1,12 +1,12 @@
|
|||||||
import os, sys, time, shlex, subprocess, shutil, requests, cv2, numpy as np
|
import os, sys, time, shlex, subprocess, shutil, requests, cv2, numpy as np
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import platform
|
import platform,socket,atexit
|
||||||
if platform.system() == 'Windows':
|
if platform.system() == 'Windows':
|
||||||
sys.path.append('e:\\libs\\')
|
sys.path.append('e:\\libs\\')
|
||||||
#sys.path.append('libs')
|
#sys.path.append('libs')
|
||||||
else:
|
else:
|
||||||
sys.path.append('/data/deploy/make3d/make2/libs/')
|
sys.path.append('/data/deploy/make3d/make2/libs/')
|
||||||
import config, libs, libs_db,main_service_db
|
import config, libs, libs_db,main_service_db,common
|
||||||
|
|
||||||
def filter_dark_texture_image(pid):
|
def filter_dark_texture_image(pid):
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
@@ -204,6 +204,7 @@ def main(pid, experience=False, makeloop=True,task_distributed_id="",isNoColorTe
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# 取云端redis任务,完成第一步的数据预处理后,将数据放入共享存储目录,将第二步任务塞入本地mysql队列
|
# 取云端redis任务,完成第一步的数据预处理后,将数据放入共享存储目录,将第二步任务塞入本地mysql队列
|
||||||
# 默认循环值守,可传参数运行单一任务,以方便调试
|
# 默认循环值守,可传参数运行单一任务,以方便调试
|
||||||
|
atexit.register(common.notify,socket.gethostname()+"建模任务已经停止")
|
||||||
pid = '0'
|
pid = '0'
|
||||||
isNoColorTexture = ""
|
isNoColorTexture = ""
|
||||||
if len(sys.argv) == 2:
|
if len(sys.argv) == 2:
|
||||||
|
|||||||
+37
-36
@@ -29,7 +29,7 @@ def make3d(pid):
|
|||||||
# psid = libs.getPSid(pid)
|
# psid = libs.getPSid(pid)
|
||||||
# if int(psid) == 80:
|
# if int(psid) == 80:
|
||||||
# change_rcbox_deepth(str(pid),0.03)
|
# change_rcbox_deepth(str(pid),0.03)
|
||||||
|
psid = libs.getPSid(pid)
|
||||||
simplify_value = 1000000 * libs.getHeadCount(pid)
|
simplify_value = 1000000 * libs.getHeadCount(pid)
|
||||||
add_photo3 = ' '
|
add_photo3 = ' '
|
||||||
#判断是否存在photo3
|
#判断是否存在photo3
|
||||||
@@ -64,48 +64,43 @@ def make3d(pid):
|
|||||||
cmd = f'{config.rcbin} {config.r1["init"]} \
|
cmd = f'{config.rcbin} {config.r1["init"]} \
|
||||||
-addFolder "{os.path.join(config.workdir, pid, "photo1")}" -addFolder "{os.path.join(config.workdir, pid, "photo2")}" {add_photo3} \
|
-addFolder "{os.path.join(config.workdir, pid, "photo1")}" -addFolder "{os.path.join(config.workdir, pid, "photo2")}" {add_photo3} \
|
||||||
-importControlPointsMeasurements "{os.path.join(config.workdir, pid, f"{pid}.controlPoints.csv")}" \
|
-importControlPointsMeasurements "{os.path.join(config.workdir, pid, f"{pid}.controlPoints.csv")}" \
|
||||||
-align -save'
|
-align -exportRegistration "{os.path.join(config.workdir,"make2", "config","exportRegistration.xml")}" "{os.path.join(config.workdir, pid,str(pid)+"_align.csv")}" -save'
|
||||||
|
|
||||||
#不存在point文件的时候就要用自动点击的方式
|
cmd = cmd + f' "{os.path.join(config.workdir, pid, f"{pid}_wait.rcproj")}"'
|
||||||
if isExistPoint == False:
|
|
||||||
cmd = cmd + f' "{os.path.join(config.workdir, pid, f"{pid}_wait.rcproj")}"'
|
|
||||||
else:
|
|
||||||
cmd = cmd + f' "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" -quit'
|
|
||||||
print(cmd)
|
print(cmd)
|
||||||
cmd = shlex.split(cmd)
|
cmd = shlex.split(cmd)
|
||||||
res = subprocess.run(cmd)
|
res = subprocess.run(cmd)
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
if isExistPoint == False:
|
|
||||||
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 定位点导入完成')
|
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 定位点导入完成')
|
||||||
|
time.sleep(3)
|
||||||
|
# defind_distance
|
||||||
|
#死循环阻塞获取
|
||||||
|
while True:
|
||||||
|
print("循环阻塞开始")
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
# defind_distance
|
#判断是否有 pid_1 的的值
|
||||||
#死循环阻塞获取
|
print(pid+"_1")
|
||||||
while True:
|
if redisLocal.lpos('model:auto_distance',pid+"_1") == None:
|
||||||
print("循环阻塞开始")
|
continue
|
||||||
time.sleep(3)
|
shutil.move(os.path.join(config.workdir, pid, f'{pid}_wait.rcproj'), os.path.join(config.workdir, pid, f'{pid}.rcproj'))
|
||||||
#判断是否有 pid_1 的的值
|
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 定义定位点距离完成')
|
||||||
print(pid+"_1")
|
#将 controlpoints_0.dat 文件拷贝到 oss 上作为公共的使用
|
||||||
if redisLocal.lpos('model:auto_distance',pid+"_1") == None:
|
common.uploadControlPointsOss(pid)
|
||||||
continue
|
|
||||||
shutil.move(os.path.join(config.workdir, pid, f'{pid}_wait.rcproj'), os.path.join(config.workdir, pid, f'{pid}.rcproj'))
|
#最后处理掉redis中的值
|
||||||
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 定义定位点距离完成')
|
redisLocal.lrem('model:auto_distance', 0, pid+"_1")
|
||||||
#将 controlpoints_0.dat 文件拷贝到 oss 上作为公共的使用
|
break
|
||||||
common.uploadControlPointsOss(pid)
|
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),"循环阻塞结束,判断是否对齐成功")
|
||||||
|
|
||||||
#最后处理掉redis中的值
|
|
||||||
redisLocal.lrem('model:auto_distance', 0, pid+"_1")
|
|
||||||
break
|
|
||||||
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),"循环阻塞结束,开始建模")
|
|
||||||
else:
|
|
||||||
#修改rcproj文件 controlpoints fileName 的引入
|
|
||||||
flag = common.changeRcprojControlpointsFile(pid)
|
|
||||||
if flag == False:
|
|
||||||
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 获取及修改controlpoints失败')
|
|
||||||
return
|
|
||||||
|
|
||||||
print("使用公共point文件的方式进行建模")
|
|
||||||
|
|
||||||
|
#查看对齐的数量
|
||||||
|
alignRes = common.isAlignNums(str(pid))
|
||||||
|
if alignRes == "rebuild":
|
||||||
|
os.system(f'python d:\\make2\\tools\push_cmd.py rebuild {pid}')
|
||||||
|
os.system(f'python d:\\make2\\main_service.py')
|
||||||
|
return
|
||||||
#区域的设置 建模
|
#区域的设置 建模
|
||||||
#update
|
#update
|
||||||
cmdSmall = "-align"
|
cmdSmall = "-align"
|
||||||
@@ -115,7 +110,10 @@ def make3d(pid):
|
|||||||
#{config.r1["init"]}
|
#{config.r1["init"]}
|
||||||
|
|
||||||
if common.task_need_high_model(pid):
|
if common.task_need_high_model(pid):
|
||||||
calulate_type = '-mvsHigh'
|
if str(psid) == "41" or str(psid) == "85":
|
||||||
|
calulate_type = "-mvs"
|
||||||
|
else:
|
||||||
|
calulate_type = '-mvsHigh'
|
||||||
else:
|
else:
|
||||||
calulate_type = '-mvs'
|
calulate_type = '-mvs'
|
||||||
|
|
||||||
@@ -164,7 +162,10 @@ def make3d(pid):
|
|||||||
else: # new version
|
else: # new version
|
||||||
#判断是否要进行高精模
|
#判断是否要进行高精模
|
||||||
if common.task_need_high_model(pid):
|
if common.task_need_high_model(pid):
|
||||||
calulate_type = 'calculateHighModel'
|
if str(psid) == "41" or str(psid) == "85":
|
||||||
|
calulate_type = "calculateNormalModel"
|
||||||
|
else:
|
||||||
|
calulate_type = 'calculateHighModel'
|
||||||
else:
|
else:
|
||||||
calulate_type = 'calculateNormalModel'
|
calulate_type = 'calculateNormalModel'
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -6,7 +6,7 @@ if platform.system() == 'Windows':
|
|||||||
#sys.path.append('libs')
|
#sys.path.append('libs')
|
||||||
else:
|
else:
|
||||||
sys.path.append('/data/deploy/make3d/make2/libs/')
|
sys.path.append('/data/deploy/make3d/make2/libs/')
|
||||||
import config, libs, libs_db,main_service_db,common
|
import config, libs, libs_db,main_service_db,common,foot_mark_seam
|
||||||
|
|
||||||
def bmesh_copy_from_object(obj, transform=True, triangulate=True, apply_modifiers=False):
|
def bmesh_copy_from_object(obj, transform=True, triangulate=True, apply_modifiers=False):
|
||||||
"""Returns a transformed, triangulated copy of the mesh"""
|
"""Returns a transformed, triangulated copy of the mesh"""
|
||||||
@@ -88,6 +88,10 @@ def base_fix(pid):
|
|||||||
bpy.context.object.location[0] = 0
|
bpy.context.object.location[0] = 0
|
||||||
bpy.context.object.location[1] = 0
|
bpy.context.object.location[1] = 0
|
||||||
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
|
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
|
||||||
|
|
||||||
|
#处理脚底UV
|
||||||
|
# basepath = os.path.join(config.workdir, pid, 'output')
|
||||||
|
# foot_mark_seam.get_obj_max_foot(basepath,os.path.join(basepath, f'{pid}.obj'),os.path.join(basepath, f'{pid}.jpg'))
|
||||||
|
|
||||||
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 模型基础校正完成,共费时{libs.diff_time(start_time)}')
|
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 模型基础校正完成,共费时{libs.diff_time(start_time)}')
|
||||||
|
|
||||||
@@ -153,7 +157,7 @@ def export_and_update_glbs(pid):
|
|||||||
# f.close()
|
# f.close()
|
||||||
|
|
||||||
# 先生成审核模型
|
# 先生成审核模型
|
||||||
faces_dest = 300000 * headcount
|
faces_dest = 500000 * headcount
|
||||||
# 减面
|
# 减面
|
||||||
faces_current = len(bpy.data.objects[pid_objname].data.polygons)
|
faces_current = len(bpy.data.objects[pid_objname].data.polygons)
|
||||||
print(f'当前面数:{faces_current},目标面数:{faces_dest}')
|
print(f'当前面数:{faces_current},目标面数:{faces_dest}')
|
||||||
|
|||||||
+27
-8
@@ -30,18 +30,21 @@ def check_pid_file(pid):
|
|||||||
else:
|
else:
|
||||||
shutil.rmtree(os.path.join(path, file))
|
shutil.rmtree(os.path.join(path, file))
|
||||||
|
|
||||||
#判断photo1 和 photo2 目录里的文件是否存在xmp 文件,不存在的话就删除
|
#判断photo1 和 photo2 目录里的文件是否存在xmp 文件,存在的话就删除
|
||||||
for file in os.listdir(os.path.join(path, 'photo1')):
|
for file in os.listdir(os.path.join(path, 'photo1')):
|
||||||
if not file.endswith('.xmp'):
|
if file.endswith('.xmp'):
|
||||||
os.remove(os.path.join(path, 'photo1', file))
|
os.remove(os.path.join(path, 'photo1', file))
|
||||||
|
|
||||||
for file in os.listdir(os.path.join(path, 'photo2')):
|
for file in os.listdir(os.path.join(path, 'photo2')):
|
||||||
if not file.endswith('.xmp'):
|
if file.endswith('.xmp'):
|
||||||
os.remove(os.path.join(path, 'photo2', file))
|
os.remove(os.path.join(path, 'photo2', file))
|
||||||
|
|
||||||
|
|
||||||
#根据参数初始化操作
|
#根据参数初始化操作
|
||||||
def cmd_run(pid,usePhoto = "1",lock=False):
|
def cmd_run(pid,usePhoto = "1",lock=False):
|
||||||
|
pid = str(pid)
|
||||||
|
#检测文件并且下载处理文件
|
||||||
|
check_pid_file(pid)
|
||||||
|
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
#文件路径
|
#文件路径
|
||||||
@@ -61,7 +64,7 @@ def cmd_run(pid,usePhoto = "1",lock=False):
|
|||||||
usePhoto = "photo"+str(usePhoto)
|
usePhoto = "photo"+str(usePhoto)
|
||||||
|
|
||||||
#执行命令
|
#执行命令
|
||||||
cmd = f'{config.rcbin} {config.r2["init"]} -setInstanceName {pid} \
|
cmd = f'{config.rcbin} {config.r2["init"]} -setInstanceName "{pid}" \
|
||||||
-save "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" \
|
-save "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" \
|
||||||
-addFolder "{os.path.join(config.workdir, pid, usePhoto)}" -selectAllImages \
|
-addFolder "{os.path.join(config.workdir, pid, usePhoto)}" -selectAllImages \
|
||||||
-detectMarkers "D:\\make2\\config\\detectMarkers.config.xml" \
|
-detectMarkers "D:\\make2\\config\\detectMarkers.config.xml" \
|
||||||
@@ -81,20 +84,36 @@ def cmd_run(pid,usePhoto = "1",lock=False):
|
|||||||
#复制xmp文件
|
#复制xmp文件
|
||||||
for xmp in os.listdir(sourceFile):
|
for xmp in os.listdir(sourceFile):
|
||||||
if xmp.endswith('.xmp'):
|
if xmp.endswith('.xmp'):
|
||||||
shutil.copy(os.path.join(sourceFile, xmp), os.path.join(targetFile,xmp))
|
if usePhoto == "photo1":
|
||||||
|
shutil.copy(os.path.join(sourceFile, xmp), os.path.join(targetFile,xmp.replace('_1.xmp', '_8.xmp')))
|
||||||
|
|
||||||
|
if usePhoto == "photo2":
|
||||||
|
shutil.copy(os.path.join(sourceFile, xmp), os.path.join(targetFile,xmp.replace('_8.xmp', '_1.xmp')))
|
||||||
|
|
||||||
|
#如果是photo2的话,就要将photo2 的 xmp 重命名成 _8.xmp
|
||||||
|
# if usePhoto == "photo2":
|
||||||
|
# for xmp in os.listdir(sourceFile):
|
||||||
|
# if xmp.endswith('.xmp'):
|
||||||
|
# #重名名.xmp 结尾的文件
|
||||||
|
# os.rename(os.path.join(sourceFile, xmp), os.path.join(sourceFile,xmp.replace('_1.xmp', '_8.xmp')))
|
||||||
|
# print("坐标复制完成")
|
||||||
|
# exit()
|
||||||
|
|
||||||
#将两组图片进行重新对齐 然后重建区域
|
#将两组图片进行重新对齐 然后重建区域
|
||||||
psid = libs.getPSid(pid)
|
psid = libs.getPSid(pid)
|
||||||
cmd = f'{config.rcbin} {config.r2["init"]} -setInstanceName {pid} \
|
cmd = f'{config.rcbin} -setInstanceName {pid} \
|
||||||
-load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" {config.r["setTextureFalse"]} \
|
-load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" {config.r["setTextureFalse"]} \
|
||||||
-addFolder "{targetFile}" -selectAllImages \
|
-addFolder "{targetFile}" -selectAllImages \
|
||||||
-detectMarkers "D:\\make2\\config\\detectMarkers.config.xml" \
|
-detectMarkers "D:\\make2\\config\\detectMarkers.config.xml" \
|
||||||
{libs.get_defineDistances(psid)} -update -align -align {config.r2["setRegion"]} \
|
{libs.get_defineDistances(psid)} -update -align -align {config.r2["setRegion"]} \
|
||||||
{exportxmp} \
|
{exportxmp} \
|
||||||
-exportReconstructionRegion "{os.path.join(config.workdir, pid, f"{pid}.rcbox")}" \
|
-exportReconstructionRegion "{os.path.join(config.workdir, pid, f"{pid}.rcbox")}" \
|
||||||
-selectImage "'+os.path.join(config.workdir,pid,'photo2')+'\*" -enableTexturingAndColoring true'
|
-selectImage "{os.path.join(config.workdir,pid,"photo2")}/*" -enableTexturingAndColoring true \
|
||||||
-save "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}"'
|
-save "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" -quit'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print(cmd)
|
print(cmd)
|
||||||
cmd = shlex.split(cmd)
|
cmd = shlex.split(cmd)
|
||||||
res = subprocess.run(cmd)
|
res = subprocess.run(cmd)
|
||||||
|
|||||||
@@ -0,0 +1,147 @@
|
|||||||
|
import os, sys, time, shlex, subprocess, shutil, requests, cv2, numpy as np
|
||||||
|
from PIL import Image
|
||||||
|
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,main_service_db
|
||||||
|
# 2. 手动操作建模做成建模
|
||||||
|
# 2.0 检测是否存在项目,不存在就下载,存在就清除项目其它无用的文件
|
||||||
|
# 2.1 初始化工程, 根据参数 加入 photo1 或者 photo 2 的 照片, 对齐 , 导出坐标, 将坐标复制到 另外一个文件夹, 测距, 重建区域, 然后调用step2
|
||||||
|
|
||||||
|
#根据pid 检测是否存在项目,不存在就下载,存在就清除项目其它无用的文件
|
||||||
|
def check_pid_file(pid):
|
||||||
|
#检测是否存在目录
|
||||||
|
path = os.path.join(config.workdir, pid)
|
||||||
|
if not os.path.exists(path):
|
||||||
|
#不存在就在就下载目录
|
||||||
|
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 开始计算相机位姿...')
|
||||||
|
start_time = time.time()
|
||||||
|
libs.down_from_oss(config.oss_bucket, config.workdir, pid,100,"2")
|
||||||
|
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} 图片下载完成,共费时{libs.diff_time(start_time)}')
|
||||||
|
else:
|
||||||
|
#存在的话就检测是否有photo1 和 photo2 之外的目录或者文件,有的话就删除
|
||||||
|
for file in os.listdir(path):
|
||||||
|
if file != 'photo1' and file != 'photo2':
|
||||||
|
if os.path.isfile(os.path.join(path, file)):
|
||||||
|
os.remove(os.path.join(path, file))
|
||||||
|
else:
|
||||||
|
shutil.rmtree(os.path.join(path, file))
|
||||||
|
|
||||||
|
#判断photo1 和 photo2 目录里的文件是否存在xmp 文件,存在的话就删除
|
||||||
|
for file in os.listdir(os.path.join(path, 'photo1')):
|
||||||
|
if file.endswith('.xmp'):
|
||||||
|
os.remove(os.path.join(path, 'photo1', file))
|
||||||
|
|
||||||
|
for file in os.listdir(os.path.join(path, 'photo2')):
|
||||||
|
if file.endswith('.xmp'):
|
||||||
|
os.remove(os.path.join(path, 'photo2', file))
|
||||||
|
|
||||||
|
|
||||||
|
#根据参数初始化操作
|
||||||
|
def cmd_run(pid,usePhoto = "2",lock=False):
|
||||||
|
pid = str(pid)
|
||||||
|
#检测文件并且下载处理文件
|
||||||
|
check_pid_file(pid)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
#文件路径
|
||||||
|
#photo1_path = os.path.join(config.workdir, pid, 'photo1')
|
||||||
|
photo2_path = os.path.join(config.workdir, pid, 'photo2')
|
||||||
|
#计算文件里的数量
|
||||||
|
#photos1_count = len(os.listdir(photo1_path))
|
||||||
|
photos2_count = len(os.listdir(photo2_path))
|
||||||
|
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} photo2数量{photos2_count}')
|
||||||
|
|
||||||
|
#xmp 坐标是要用 lock的 还是 unlock 的
|
||||||
|
if lock:
|
||||||
|
exportxmp = ' -exportXMP "D:\\make2\\config\\exportXMP.config.lock.xml" '
|
||||||
|
else:
|
||||||
|
exportxmp = ' -exportXMP "D:\\make2\\config\\exportXMP.config.xml" '
|
||||||
|
|
||||||
|
usePhoto = "photo"+str(usePhoto)
|
||||||
|
|
||||||
|
#执行命令
|
||||||
|
cmd = f'{config.rcbin} {config.r2["init"]} -setInstanceName "{pid}" \
|
||||||
|
-save "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" \
|
||||||
|
-addFolder "{os.path.join(config.workdir, pid, usePhoto)}" -selectAllImages \
|
||||||
|
-detectMarkers "D:\\make2\\config\\detectMarkers.config.xml" \
|
||||||
|
-align -align \
|
||||||
|
{exportxmp} \
|
||||||
|
-save "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" -quit'
|
||||||
|
print(cmd)
|
||||||
|
cmd = shlex.split(cmd)
|
||||||
|
res = subprocess.run(cmd)
|
||||||
|
|
||||||
|
#根据参数转变路劲,复制photo1 里的xmp 文件到 photo2 里,或者 photo2 里的xmp 文件到 photo1 里
|
||||||
|
# sourceFile = photo1_path
|
||||||
|
targetFile = photo2_path
|
||||||
|
# if usePhoto == "photo2":
|
||||||
|
# sourceFile = photo2_path
|
||||||
|
# targetFile = photo1_path
|
||||||
|
# #复制xmp文件
|
||||||
|
# for xmp in os.listdir(sourceFile):
|
||||||
|
# if xmp.endswith('.xmp'):
|
||||||
|
# if usePhoto == "photo1":
|
||||||
|
# shutil.copy(os.path.join(sourceFile, xmp), os.path.join(targetFile,xmp.replace('_1.xmp', '_8.xmp')))
|
||||||
|
|
||||||
|
# if usePhoto == "photo2":
|
||||||
|
# shutil.copy(os.path.join(sourceFile, xmp), os.path.join(targetFile,xmp.replace('_8.xmp', '_1.xmp')))
|
||||||
|
|
||||||
|
#如果是photo2的话,就要将photo2 的 xmp 重命名成 _8.xmp
|
||||||
|
# if usePhoto == "photo2":
|
||||||
|
# for xmp in os.listdir(sourceFile):
|
||||||
|
# if xmp.endswith('.xmp'):
|
||||||
|
# #重名名.xmp 结尾的文件
|
||||||
|
# os.rename(os.path.join(sourceFile, xmp), os.path.join(sourceFile,xmp.replace('_1.xmp', '_8.xmp')))
|
||||||
|
# print("坐标复制完成")
|
||||||
|
# exit()
|
||||||
|
|
||||||
|
#将两组图片进行重新对齐 然后重建区域
|
||||||
|
psid = libs.getPSid(pid)
|
||||||
|
cmd = f'{config.rcbin} -setInstanceName {pid} \
|
||||||
|
-load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}"\
|
||||||
|
-detectMarkers "D:\\make2\\config\\detectMarkers.config.xml" \
|
||||||
|
{libs.get_defineDistances(psid)} -update -align -align -align -align -align -align {config.r2["setRegion"]} \
|
||||||
|
{exportxmp} \
|
||||||
|
-exportReconstructionRegion "{os.path.join(config.workdir, pid, f"{pid}.rcbox")}" \
|
||||||
|
-selectImage "{os.path.join(config.workdir,pid,"photo2")}/*" -enableTexturingAndColoring true \
|
||||||
|
-save "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" -quit'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print(cmd)
|
||||||
|
cmd = shlex.split(cmd)
|
||||||
|
res = subprocess.run(cmd)
|
||||||
|
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} step1完成,共费时{libs.diff_time(start_time)}')
|
||||||
|
|
||||||
|
#调用step2
|
||||||
|
time.sleep(2)
|
||||||
|
os.system(f'python main_step2.py {pid}')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) == 2:
|
||||||
|
pids = sys.argv[1].split(',')
|
||||||
|
for pid in pids:
|
||||||
|
cmd_run(pid,usePhoto = "1",lock=False)
|
||||||
|
elif len(sys.argv) == 3:
|
||||||
|
pids = sys.argv[1].split(',')
|
||||||
|
for pid in pids:
|
||||||
|
if sys.argv[2] == '2':
|
||||||
|
cmd_run(pid,usePhoto = "2",lock=False)
|
||||||
|
else:
|
||||||
|
cmd_run(pid,usePhoto = "1",lock=False)
|
||||||
|
elif len(sys.argv) == 4:
|
||||||
|
pids = sys.argv[1].split(',')
|
||||||
|
usePhoto = sys.argv[2]
|
||||||
|
lock = sys.argv[3]
|
||||||
|
for pid in pids:
|
||||||
|
cmd_run(pid,usePhoto = usePhoto,lock=lock)
|
||||||
|
|
||||||
|
else:
|
||||||
|
print(f'useage: python {sys.argv[0]} pid1,pid2,pid3 photo = 1/2 lock = True/False')
|
||||||
|
sys.exit(1)
|
||||||
+8
-12
@@ -1,10 +1,10 @@
|
|||||||
import platform,sys,redis,time,requests,json
|
import platform,sys,redis,time,requests,json,atexit
|
||||||
if platform.system() == 'Windows':
|
if platform.system() == 'Windows':
|
||||||
sys.path.append('e:\\libs\\')
|
sys.path.append('e:\\libs\\')
|
||||||
else:
|
else:
|
||||||
sys.path.append('/data/deploy/make3d/make2/libs/')
|
sys.path.append('/data/deploy/make3d/make2/libs/')
|
||||||
|
|
||||||
import config,libs,libs_db
|
import config,libs,libs_db,common
|
||||||
r = redis.Redis(host="106.14.158.208",password="kcV2000",port=6379,db=6)
|
r = redis.Redis(host="106.14.158.208",password="kcV2000",port=6379,db=6)
|
||||||
def getPSid(pid):
|
def getPSid(pid):
|
||||||
res = requests.get("https://mp.api.suwa3d.com/api/customerP3dLog/photoStudio",params={"pid":pid})
|
res = requests.get("https://mp.api.suwa3d.com/api/customerP3dLog/photoStudio",params={"pid":pid})
|
||||||
@@ -43,21 +43,17 @@ def readTask(key):
|
|||||||
print("走新的建模系统不是分布式插入-重建工单",key,pid,psid)
|
print("走新的建模系统不是分布式插入-重建工单",key,pid,psid)
|
||||||
libs_db.add_task(taskData)
|
libs_db.add_task(taskData)
|
||||||
else:
|
else:
|
||||||
|
if int(psid) <= 90 and int(psid) != 29 and int(psid) != 56:
|
||||||
if int(psid) == 41 or int(psid) == 85:
|
print("走分布式建模",key,pid,psid)
|
||||||
taskData["priority"] = 0
|
if int(psid) == 41 or int(psid) == 85:
|
||||||
print("走分布式建模系统插入",key,pid,psid)
|
taskData["priority"] = 0
|
||||||
libs_db.add_task_distributed(taskData)
|
|
||||||
if libs_db.isStudioConfigDistribute(psid):
|
|
||||||
print("走分布式建模系统插入",key,pid,psid)
|
|
||||||
libs_db.add_task_distributed(taskData)
|
libs_db.add_task_distributed(taskData)
|
||||||
else:
|
else:
|
||||||
print("走新的建模系统不是分布式插入",key,pid,psid)
|
print("非分布式建模",key,pid,psid)
|
||||||
libs_db.add_task(taskData)
|
libs_db.add_task(taskData)
|
||||||
|
|
||||||
#程序主入口
|
#程序主入口
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
atexit.register(common.notify,"定时读取建模任务已经停止")
|
||||||
#print(r.llen('model:make10'))
|
#print(r.llen('model:make10'))
|
||||||
#开启死循环
|
#开启死循环
|
||||||
while True:
|
while True:
|
||||||
|
|||||||
+3
-1
@@ -17,6 +17,8 @@ def main(cmd, order_id):
|
|||||||
key = 'model:make10'
|
key = 'model:make10'
|
||||||
elif cmd == 'foot': # print_id
|
elif cmd == 'foot': # print_id
|
||||||
key = 'model:foot'
|
key = 'model:foot'
|
||||||
|
elif cmd == 'rebuild': #pid
|
||||||
|
key = 'model:rebuild'
|
||||||
|
|
||||||
if order_id == 'view':
|
if order_id == 'view':
|
||||||
for i in r.lrange(key, 0, -1):
|
for i in r.lrange(key, 0, -1):
|
||||||
@@ -142,7 +144,7 @@ if __name__ == '__main__':
|
|||||||
r = config.redis_remote
|
r = config.redis_remote
|
||||||
|
|
||||||
#pid 可能是多个的,用逗号分隔,查询的时候接口应该也要支持多个的
|
#pid 可能是多个的,用逗号分隔,查询的时候接口应该也要支持多个的
|
||||||
if cmd == 'make3d' or cmd == 'make3d10':
|
if cmdName == 'make3d' or cmdName == 'make3d10' or cmdName == 'rebuild':
|
||||||
main(cmdName, pid)
|
main(cmdName, pid)
|
||||||
elif cmd != "":
|
elif cmd != "":
|
||||||
cmd(cmdName,pid)
|
cmd(cmdName,pid)
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
#建模完成,需要减面 smooth 封闭洞 清理模型 贴图
|
||||||
|
%bin% -delegateTo %pid% -simplify 3000000 -smooth -closeHoles -cleanModel -calculateTexture -save "D:\123446\123446.rcproj" -exportSelectedModel "D:\123446\output\123446.obj" "d:\make2\config\ModelExportParams.xml" -quit
|
||||||
Reference in new issue
Block a user