diff --git a/export_build_info/__pycache__/export_already_build.cpython-310.pyc b/export_build_info/__pycache__/export_already_build.cpython-310.pyc
new file mode 100644
index 0000000..fd97af8
Binary files /dev/null and b/export_build_info/__pycache__/export_already_build.cpython-310.pyc differ
diff --git a/export_build_info/already.txt b/export_build_info/already.txt
new file mode 100644
index 0000000..e69de29
diff --git a/export_build_info/check.py b/export_build_info/check.py
new file mode 100644
index 0000000..df76b80
--- /dev/null
+++ b/export_build_info/check.py
@@ -0,0 +1,125 @@
+import os, sys, time, shlex, subprocess, shutil, requests, cv2, numpy as np
+from PIL import Image
+import platform,socket,atexit
+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,common
+
+arrPids = [184219,184215,184209,184206,184201,184199,184164,184087,184076,184069,184059,184029,184013,183993,183952,183888,183882,183868,183824,183817,183815,183812,183791,183777,183715,183705,183670,183613,183573,182974,182983,182985,182989,182997,183007,183051,183060,183054,183053,183097,183119,183108,183139,183141,183155,183163,183169,183180,183191,183196,183214,183244,183266,183278,183275,183309,183402,183422,183440,182974,182964,182958,182956,182916,182855,182854,182820,182787,182800,182809,182780,182772,182770,182766,182754,182742,182740,182723,182707,182647,182643,182614,182595,182563,182557,182547,182546,182538,182530,182517,182498,182478,182452,182386,182352,182285,182266,182260,182230,182224]
+
+r12Pids = [184219,184215,184209,184069,184059,183868,183817,183791,183613,183573,182974,182983,182985,182989,182997,183007,183051,183060,183054,183053,183097,183119,183108,183139,183141,183155,183163,183169,183180,183191,183196,183214,183244,183266,183278,183275,183309,183402,183422,183440,182974,182964,182958,182855,182854]
+print(f"处理的数据长度--{len(arrPids)}")
+i=0
+noPids = ''
+for pid in r12Pids:
+ pid = str(pid)
+ path = f"D://{pid}/mask"
+ #判断是否存在文件夹
+ if not os.path.exists(path):
+ continue
+
+ #判断文件夹是否为空
+ if len(os.listdir(path)) == 0:
+ continue
+
+ i+=1
+
+
+ #检查 depth 和 mask 的文件创建时间是否差异比较大
+ fileDepth = f"D://{pid}/depth"
+ fileMask = f"D://{pid}/mask"
+
+ diffDepthTime = []
+ dfffMaskTime = []
+
+ arrTimeDepth = []
+ arrTimeMask = []
+ for file in os.listdir(fileDepth):
+ createTime = os.path.getctime(f"{fileDepth}/{file}")
+ updateTime = os.path.getmtime(f"{fileDepth}/{file}")
+ # print(updateTime - createTime)
+ diffDepthTime.append(updateTime - createTime)
+ arrTimeDepth.append(os.path.getctime(f"{fileDepth}/{file}"))
+
+ for file in os.listdir(fileMask):
+ createTime = os.path.getctime(f"{fileMask}/{file}")
+ updateTime = os.path.getmtime(f"{fileMask}/{file}")
+ dfffMaskTime.append(updateTime - createTime)
+
+ arrTimeMask.append(os.path.getctime(f"{fileMask}/{file}"))
+
+ #打印出 两者的 最大 和最小的时间信息
+ print(f"pid: {pid} depth: { (max(arrTimeDepth) - min(arrTimeDepth))/60 }, diffdepth: {max(diffDepthTime)}, mask: { (max(arrTimeMask) - min(arrTimeMask))/60},diffmask: {max(dfffMaskTime)}")
+ # print(f"pid: {pid} diffdepth: {max(arrTimeDepth)} diffmask: {max(arrTimeMask)}")
+
+ diffDepth = (max(arrTimeDepth) - min(arrTimeDepth))/60
+ diffMask = (max(arrTimeMask) - min(arrTimeMask))/60
+
+ if diffDepth > 5 or diffMask > 5:
+ print(f"异常数据 pid: {pid} depth: {diffDepth} mask: {diffMask}")
+ break
+
+ #复制文件到指定目录
+ maskPath = f"D://{pid}/mask"
+ depthPath = f"D://{pid}/depth"
+ regPath = f"D://{pid}/reg"
+ imageList = f"D://{pid}/{pid}_imageList.txt"
+ outFila = f"D://{pid}/reg/{pid}_registration.out"
+
+ sourcePath = f"D://model_info/{pid}"
+ if os.path.exists(sourcePath):
+ shutil.rmtree(sourcePath)
+
+ if not os.path.exists(sourcePath):
+ os.makedirs(sourcePath)
+
+ #复制文件
+ shutil.copytree(maskPath, f"D://model_info/{pid}/mask")
+ shutil.copytree(depthPath, f"D://model_info/{pid}/depth")
+ shutil.copy(imageList, f"D://model_info/{pid}/{pid}_imageList.txt")
+ shutil.copy(outFila, f"D://model_info/{pid}/{pid}_registration.out")
+
+ #遍历reg文件夹
+ for file in os.listdir(regPath):
+ if file == f"{pid}_registration.out":
+ continue
+
+ if "_1.jpg" in file:
+ sourceTempPath = f"D://model_info/{pid}/reg/photo1"
+ if not os.path.exists(sourceTempPath):
+ os.makedirs(sourceTempPath)
+ shutil.copy(f"{regPath}/{file}", f"{sourceTempPath}/{file}")
+
+ if "_8.jpg" in file:
+ sourceTempPath = f"D://model_info/{pid}/reg/photo2"
+ if not os.path.exists(sourceTempPath):
+ os.makedirs(sourceTempPath)
+ shutil.copy(f"{regPath}/{file}", f"{sourceTempPath}/{file}")
+
+ #shutil.copy(f"{regPath}/{file}", f"D://model_info/{pid}/reg/{file}")
+
+ #移除 reg 里的 {pid}_registration.out
+
+
+ print(f"处理完成 pid: {pid}")
+
+
+
+
+ # shutil.copytree(f"D://{pid}", f"D://{pid}_bak")
+
+
+
+ # cmd = f'{config.rcbin} {config.r2["init"]} -setInstanceName {pid} \
+ # -load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}"'# -quit
+ # print(cmd)
+ # cmd = shlex.split(cmd)
+ # res = subprocess.run(cmd)
+
+
+
+
+#print(i)
\ No newline at end of file
diff --git a/export_build_info/depth_mask_config.xml b/export_build_info/depth_mask_config.xml
new file mode 100644
index 0000000..79e3937
--- /dev/null
+++ b/export_build_info/depth_mask_config.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/export_build_info/err.pid b/export_build_info/err.pid
new file mode 100644
index 0000000..e69de29
diff --git a/export_build_info/export_already_build.py b/export_build_info/export_already_build.py
new file mode 100644
index 0000000..75cb8db
--- /dev/null
+++ b/export_build_info/export_already_build.py
@@ -0,0 +1,206 @@
+import os, sys, shutil, subprocess, shlex,oss2,requests
+sys.path.append('e:\\libs\\')
+import config
+import xml.etree.ElementTree as ET
+import common
+def is_already(pid):
+
+ if not os.path.exists("D://make2/export_build_info/finished.txt"):
+ #创建文件
+ with open("D://make2/export_build_info/finished.txt", 'w') as f:
+ f.write("")
+ return False
+ #读取已经完成的pid
+ with open("D://make2/export_build_info/finished.txt", 'r') as f:
+ lines = f.readlines()
+ for line in lines:
+ if str(pid) == str(line.strip()):
+ return True
+ return False
+
+
+
+
+
+def writeImageList(pid):
+ # pid = "185005"
+ imageListTxt = f"D://{pid}/{pid}_imageList.txt"
+ if not os.path.exists(imageListTxt):
+ with open(imageListTxt, 'w') as f:
+ f.write("")
+ filePath = f"D://{pid}//{pid}.rcproj"
+ tree = ET.parse(filePath)
+ root = tree.getroot()
+ fileName = []
+ for input_tag in root.findall(".//input"):
+ tempFileName = input_tag.get("fileName")
+ if tempFileName:
+ fileName.append(tempFileName)
+ sourceFileNames = []
+ for sourceFile in fileName:
+ tempSourceName = sourceFile.replace(f"D:\{pid}\photo1\\","")
+ tempSourceName = tempSourceName.replace(f"D:\{pid}\photo2\\","")
+ print("tempSourceName",tempSourceName)
+ #遍历指定的文件减价
+ for file in os.listdir(f"D://{pid}/depthAndMask"):
+ if ".jpg.depth.exr" not in file:
+ continue
+ #截取图片名称
+ tempName = file.replace(".depth.exr","")
+ if tempName == tempSourceName:
+ #sourceFileNames.append(sourceFile)
+ #写入到文件中
+ print(f"写入到文件-{sourceFile}")
+ with open(imageListTxt, 'a+') as f:
+ f.write(f"{sourceFile}\n")
+
+
+def exportInfo(pid):
+ newCopyFilePath = f"D://{pid}/{pid}.rcproj"
+ #判断是否存在目录,不存在则创建
+ depthMaskPath = f"D://{pid}/depthAndMask"
+ #删除文件夹
+ try:
+ shutil.rmtree(depthMaskPath)
+ except Exception as e:
+ print(e)
+
+
+ if not os.path.exists(f"D://{pid}/depthAndMask"):
+ os.makedirs(f"D://{pid}/depthAndMask")
+
+ imageListTxt = f"D://{pid}/{pid}_imageList.txt"
+ try:
+ os.remove(imageListTxt)
+ except Exception as e:
+ print(e)
+
+ if not os.path.exists(imageListTxt):
+ with open(imageListTxt, 'w') as f:
+ f.write("")
+
+ maskPath = f"D://{pid}/mask"
+
+ try:
+ shutil.rmtree(maskPath)
+ except Exception as e:
+ print(f"删除文件夹失败{e}")
+ if not os.path.exists(f"D://{pid}/mask"):
+ os.makedirs(f"D://{pid}/mask")
+
+ depthPath = f"D://{pid}/depth"
+ try:
+ shutil.rmtree(depthPath)
+ except Exception as e:
+ print(e)
+
+ if not os.path.exists(f"D://{pid}/depth"):
+ os.makedirs(f"D://{pid}/depth")
+
+ registrationPath = f"D://{pid}/reg"
+ try:
+ shutil.rmtree(registrationPath)
+ except Exception as e:
+ print(e)
+ if not os.path.exists(registrationPath):
+ os.makedirs(registrationPath)
+
+ #如果存在则执行打开命令
+ cmd = f'{config.rcbin} {config.r2["init"]} -setInstanceName {pid} -load "{newCopyFilePath}" -exportRegistration "D://{pid}/reg/{pid}_registration.out" "D://make2/config/registration_export_config.xml" -exportDepthAndMask "D://{pid}/depthAndMask" "D://make2/config/depth_mask_config.xml" -quit'
+ # print(cmd)
+ cmd = shlex.split(cmd)
+ res = subprocess.run(cmd)
+
+ writeImageList(pid)
+
+ #删除掉 depthMaskPath 里 文件名 包含 _1. 的文件
+ for file in os.listdir(depthMaskPath):
+ #将遍历出来的文件名进行判断,如果是_8.jpg.mask _1.jpg.mask 写入到pid_imgList.txt中
+ # if "_8.jpg.mask" in file:
+ # jpgPath = f"D://{pid}/photo2/"+file.replace(".mask", "")
+ # jpgPath = jpgPath.replace(".png", "")
+ # print("_8",jpgPath)
+ # with open(imageListTxt, 'a+') as f:
+ # f.write(f"{jpgPath}\n")
+
+ # if "_1.jpg.mask" in file:
+ # jpgPath = f"D://{pid}/photo1/"+file.replace(".mask", "")
+ # jpgPath = jpgPath.replace(".png", "")
+ # print("_1",jpgPath)
+ # with open(imageListTxt, 'a+') as f:
+ # f.write(f"{jpgPath}\n")
+
+ if "_1." in file:
+ os.remove(f"{depthMaskPath}/{file}")
+
+ if "_8.jpg.mask" in file:
+ try:
+ shutil.move(f"{depthMaskPath}/{file}",maskPath)
+ except Exception as e:
+ print(f"移动文件失败1{e}")
+
+
+ if "_8.jpg.depth" in file:
+ try:
+ shutil.move(f"{depthMaskPath}/{file}",depthPath)
+ except Exception as e:
+ print(f"移动文件失败2{e}")
+
+
+ writeImageList(str(pid))
+
+ #删除已存在数据,防止版本冲突
+ try:
+ deleteList = []
+ for obj in oss2.ObjectIterator(config.oss_bucket,prefix=f'objs/auto/{pid}/model_info_v2'):
+ deleteList.append(obj.key)
+ config.oss_bucket.batch_delete_objects(deleteList)
+ except Exception as e:
+ print("")
+
+ #上传到oss 上
+ #将 D:\{pid}\{pid}_registration.out 上传到 oss model_info
+ config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/model_info_v2/{pid}_registration.out', f'D://{pid}/reg/{pid}_registration.out')
+ # imageList.txt
+ config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/model_info_v2/{pid}_imageList.txt', imageListTxt)
+ if os.path.exists(f"{depthMaskPath}/imageList.txt"):
+ config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/model_info_v2/imageList.txt', f"{depthMaskPath}/imageList.txt")
+ # depth 和 mask 上传
+ print("上传 mask")
+ for file in os.listdir(maskPath):
+ config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/model_info_v2/mask/{file}', f"{maskPath}/{file}")
+
+ print("上传 depth")
+ for file in os.listdir(depthPath):
+ config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/model_info_v2/depth/{file}', f"{depthPath}/{file}")
+
+ #上传几遍照片
+ print("上传 reg")
+ for file in os.listdir(registrationPath):
+ if "_1.jpg" in file:
+ config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/model_info_v2/reg/photo1/{file}', f"{registrationPath}/{file}")
+
+ if "_8.jpg" in file:
+ config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/model_info_v2/reg/photo2/{file}', f"{registrationPath}/{file}")
+
+ tempFile = f"D://{pid}//finish.txt"
+ #创建文件
+ with open(tempFile, 'w') as f:
+ f.write("")
+
+ print(f"完成的PID-{pid}")
+
+
+ #写入到指定的文件中
+ with open("D://make2/pid.text", 'a+') as f:
+ f.write(f"{pid},")
+
+ #删除文件
+ # common.removeFolder(str(pid))
+ # shutil.rmtree(f"D://{pid}",ignore_errors=True)
+
+ #插入队列
+ tempUrl = "https://mp.api.suwa3d.com/api/customerP3dLog/addGaussianRedisQueneu?pid="+str(pid)
+ requests.get(tempUrl)
+
+# exportInfo("181593")
\ No newline at end of file
diff --git a/export_build_info/finish.txt b/export_build_info/finish.txt
new file mode 100644
index 0000000..4f0850d
--- /dev/null
+++ b/export_build_info/finish.txt
@@ -0,0 +1,90 @@
+146134
+146134
+146598
+183716
+185381
+183400
+187752
+184871
+184956
+185326
+187651
+187802
+187811
+187800
+183096
+187804
+184956
+187808
+187898
+187865
+187870
+187886
+187912
+185102
+185102
+185102
+187450
+185102
+187989
+188170
+188117
+188128
+188200
+188297
+188310
+188344
+185101
+188425
+188428
+188431
+188560
+188494
+188564
+188757
+188779
+188807
+188865
+188827
+188910
+188907
+188913
+188942
+188964
+189045
+189051
+189203
+189214
+189218
+189228
+189246
+189242
+189373
+189312
+189388
+189913
+189911
+189932
+189946
+189106
+186427
+186544
+190092
+190112
+188681
+190138
+188688
+189172
+183292
+189178
+184093
+183080
+189608
+189625
+189618
+189170
+189623
+190151
+183309
+190214
+188521
diff --git a/export_build_info/finished.txt b/export_build_info/finished.txt
new file mode 100644
index 0000000..e69de29
diff --git a/export_build_info/gen_xmps_for_build_info.py b/export_build_info/gen_xmps_for_build_info.py
new file mode 100644
index 0000000..8a7a741
--- /dev/null
+++ b/export_build_info/gen_xmps_for_build_info.py
@@ -0,0 +1,124 @@
+import os, sys, time, shutil, subprocess, shlex, json,oss2
+import platform
+if platform.system() == 'Windows':
+ sys.path.append('e:\\libs\\')
+else:
+ sys.path.append('/data/deploy/make3d/make2/libs/')
+
+import config, libs, libs_db
+
+def upload_xmp(pid):
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 上传xmp文件之前先删除oss上的xmp文件所在目录...')
+ pid = str(pid)
+ psid = libs.getPSid(pid)
+ #移除掉旧的文件夹
+ #config.oss_bucket.delete_object(f'xmps/{pid}/')
+ #删除oss 上的文件夹里的内容
+
+ #判断是否存在该目录
+ if config.oss_bucket.object_exists(f'xmps/{psid}/') == True:
+ object_list = oss2.ObjectIterator(config.oss_bucket, prefix=f'xmps/{psid}/')
+ if not any(object_list):
+ config.oss_bucket.batch_delete_objects([obj.key for obj in object_list])
+
+ start_time = time.time()
+ workdir = os.path.join(config.workdir, pid)
+ ##psid = libs.getPSid(pid)
+ config.oss_bucket.put_object_from_file(f'xmps/{psid}/{psid}.rcbox', os.path.join(workdir, f'{pid}.rcbox'))
+ for xmp in os.listdir(os.path.join(workdir, 'photo1')):
+ if xmp.endswith('.xmp'):
+ config.oss_bucket.put_object_from_file(f'xmps/{psid}/mesh/{xmp}', os.path.join(workdir, 'photo1', xmp))
+ for xmp in os.listdir(os.path.join(workdir, 'photo2')):
+ if xmp.endswith('.xmp'):
+ config.oss_bucket.put_object_from_file(f'xmps/{psid}/texture/{xmp}', os.path.join(workdir, 'photo2', xmp))
+
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} xmp文件上传完成,共费时{time.time() - start_time}秒')
+
+def main(pid, lock=False):
+ 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)
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} 图片下载完成,共费时{libs.diff_time(start_time)}')
+
+ 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))
+ # if photos1_count + photos2_count < 164:
+ # print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} photo1数量{photos1_count} photo2数量{photos2_count},未能覆盖所有相机,是否继续计算相机位姿?')
+ # continue_or_not = input('是否继续计算相机位姿?(y/n)')
+ # if continue_or_not == 'y':
+ # pass
+ # else:
+ # sys.exit(0)
+
+ if lock:
+ exportxmp = ' -exportXMP "D:\\make2\\config\\exportXMP.config.lock.xml" '
+ else:
+ exportxmp = ' -exportXMP "D:\\make2\\config\\exportXMP.config.xml" '
+
+ 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, "photo1")}" -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)
+
+ # TODO:加入report相机位姿质量评估
+
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} photo1相机位姿完成,共费时{libs.diff_time(start_time)}')
+
+ for xmp in os.listdir(photo1_path):
+ if xmp.endswith('.xmp'):
+ shutil.copy(os.path.join(photo1_path, xmp), os.path.join(photo2_path, xmp.replace('_1.xmp', '_8.xmp')))
+
+ psid = libs.getPSid(pid)
+ cmd = f'{config.rcbin} {config.r2["init"]} -setInstanceName {pid} \
+ -load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" {config.r["setTextureFalse"]} \
+ -addFolder "{os.path.join(config.workdir, pid, "photo2")}" -selectAllImages \
+ -detectMarkers "D:\\make2\\config\\detectMarkers.config.xml" \
+ {libs.get_defineDistances(psid)} -update -align -align {config.r2["setRegion"]} \
+ {exportxmp} \
+ -exportReconstructionRegion "{os.path.join(config.workdir, pid, f"{pid}.rcbox")}" \
+ -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} photo2相机位姿完成,共费时{libs.diff_time(start_time)}')
+
+ # # TODO:加入report相机位姿质量评估
+ # if not lock:
+ # upload_or_not = input('是否上传oss?(y/n)')
+ # if upload_or_not == 'y':
+ # upload_xmp(pid)
+ # #上传坐标的话要判断该影棚是否走新的建模系统,如果不是走新的建模系统,就要更新为走新的建模系统
+ # libs_db.change_to_new_make_psid(psid)
+ # print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} xmp文件上传完成,共费时{libs.diff_time(start_time)}')
+
+ # delete_or_not = input('是否删除本地文件?(y/n)')
+ # if delete_or_not == 'y':
+ # shutil.rmtree(os.path.join(config.workdir, pid))
+ # print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} 本地文件已删除')
+ # else:
+ # print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} 本地文件未删除')
+
+if __name__ == '__main__':
+ if len(sys.argv) == 2:
+ pids = sys.argv[1].split(',')
+ for pid in pids:
+ main(pid)
+ elif len(sys.argv) == 3:
+ pids = sys.argv[1].split(',')
+ for pid in pids:
+ if sys.argv[2] == 'lock':
+ main(pid, lock=True)
+ else:
+ main(pid, lock=False)
+ else:
+ print(f'useage: python {sys.argv[0]} pid1,pid2,pid3 [lock]')
+ sys.exit(1)
\ No newline at end of file
diff --git a/export_build_info/main_step1.py b/export_build_info/main_step1.py
new file mode 100644
index 0000000..ac4b257
--- /dev/null
+++ b/export_build_info/main_step1.py
@@ -0,0 +1,340 @@
+import os, sys, time, shlex, subprocess, shutil, requests, cv2, numpy as np
+from PIL import Image
+import platform,socket,atexit
+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,common
+
+def filter_dark_texture_image(pid):
+ start_time = time.time()
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 开始检测射灯异常图片...')
+ def get_image_v(image):
+ # 图片左上角和右上角各取200*200区域,计算V通道均值
+ left_rect = image[0:200, 0:200]
+ right_rect = image[0:200, -200:]
+
+ left_hsv = cv2.cvtColor(left_rect, cv2.COLOR_BGR2HSV)
+ left_v = left_hsv[:, :, 2]
+ left_avg_v = np.mean(left_v)
+ # print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 图片左上角V通道均值:{left_avg_v}')
+
+ right_hsv = cv2.cvtColor(right_rect, cv2.COLOR_BGR2HSV)
+ right_v = right_hsv[:, :, 2]
+ right_avg_v = np.mean(right_v)
+ # print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 图片右上角V通道均值:{right_avg_v}')
+
+ return (left_avg_v + right_avg_v) / 2
+
+ v_list = []
+ for filename in os.listdir(os.path.join(config.workdir, pid, 'photo2')):
+ if filename.endswith(".jpg"):
+ image = cv2.imread(os.path.join(config.workdir, pid, 'photo2', filename))
+ v = get_image_v(image)
+ item = {'filename': filename, 'v': v}
+ v_list.append(item)
+ v_list.sort(key=lambda x: x['v'])
+ v_list = v_list[5: -5]
+ avg_v = np.mean([item['v'] for item in v_list])
+ for item in v_list:
+ if abs(item['v'] - avg_v) > 50:
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 图片{item["filename"]} V通道值{item["v"]},低于平均值{avg_v},将不参与贴图')
+ libs.set_photo_join_type(config.workdir, pid, 'photo2', item['filename'].split('_')[0], mesh='1', texture='0')
+
+ # 复制xmp文件到photo3目录,如果photo3目录存在的话
+ if os.path.exists(os.path.join(config.workdir, pid, 'photo3')):
+ shutil.copyfile(os.path.join(config.workdir, pid, 'photo2', item['filename'].replace('jpg', 'xmp')), os.path.join(config.workdir, pid, 'photo3', item['filename'].replace('jpg', 'xmp')))
+
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 射灯异常图片检测完成,共费时{libs.diff_time(start_time)}')
+
+def detect_markers(psid, pid):
+ def fix_region():
+ region_filename = os.path.join(config.workdir, pid, f'{pid}.rcbox')
+ with open(region_filename, 'r') as f:
+ lines = f.readlines()
+ lines = [line.replace('"NONE" globalCoordinateSystemWkt="NONE" globalCoordinateSystemName="NONE"', '"+proj=geocent +ellps=WGS84 +no_defs" globalCoordinateSystemName="local:1 - Euclidean"') for line in lines]
+
+ start_time = time.time()
+ add_photo3 = ' '
+ textpicCmd = ' '
+ if os.path.exists(os.path.join(config.workdir, pid, 'photo3')):
+ add_photo3 = ' -addFolder "' + os.path.join(config.workdir, pid, 'photo3') + '" '
+
+ textpicCmd ='-selectImage "'+os.path.join(config.workdir,pid,'photo3')+'\*" -enableTexturingAndColoring true'
+ textpicCmd ='-selectImage "'+os.path.join(config.workdir,pid,'photo2')+'\*" -enableTexturingAndColoring false'
+ else:
+ textpicCmd ='-selectImage "'+os.path.join(config.workdir,pid,'photo2')+'\*" -enableTexturingAndColoring true'
+
+ 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, "photo1")}" {config.r["setTextureFalse"]} -align -addFolder "{os.path.join(config.workdir, pid, "photo2")}" \
+ {add_photo3} -align -selectAllImages \
+ -detectMarkers "D:\\make2\\config\\detectMarkers.config.xml" \
+ {libs.get_defineDistances(psid)} -align -align -update {config.r2["setRegion"]} \
+ -exportXMP "D:\\make2\\config\\exportXMP.config.xml" \
+ -exportControlPointsMeasurements "{os.path.join(config.workdir, pid, f"{pid}.controlPoints.csv")}" "D:\\make2\\config\\exportControlPoints.config.xml" \
+ -exportReconstructionRegion "{os.path.join(config.workdir, pid, f"{pid}.rcbox")}" \
+ {textpicCmd} -save "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" -quit'
+ print(cmd)
+ cmd = shlex.split(cmd)
+ res = subprocess.run(cmd)
+ time.sleep(3)
+ fix_region()
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 定位点检测完成, 共费时{libs.diff_time(start_time)}')
+
+ if os.path.exists(os.path.join(config.workdir, pid, 'photo3')):
+ for filename in os.listdir(os.path.join(config.workdir, pid, 'photo2')):
+ if filename.endswith('_8.xmp'):
+ # photo3 exist, 设置photo2的xmp文件,不参与贴图
+ libs.set_photo_join_type(config.workdir, pid, 'photo2', filename.split('_')[0], mesh='1', texture='0')
+ for filename in os.listdir(os.path.join(config.workdir, pid, 'photo3')):
+ if filename.endswith('_8.xmp'):
+ # photo3 exist, 设置photo3的xmp文件,不参与建模
+ libs.set_photo_join_type(config.workdir, pid, 'photo3', filename.split('_')[0], mesh='0', texture='1')
+
+def step1(pid, experience=False, makeloop=True,task_distributed_id="",isNoColorTexture=""):
+ libs_db.start_task({"task_type": "make", "task_key": pid})
+
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 开始处理{pid}建模任务')
+ psid = libs.getPSid(pid)
+
+ # 更新云端任务状态
+ res = requests.post(config.urls['update_status_modeling_url'], data={'id': pid})
+ print('更新建模中状态:', res.text)
+
+ # 下载图片
+ start_time = time.time()
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} 开始下载图片...')
+ libs.down_from_oss(config.oss_bucket, config.workdir, pid)
+ try:
+ if str(psid) == "86":
+ #移除指定文件
+ os.remove(f"D:\{pid}\photo1\\21_1.jpg")
+ os.remove(f"D:\{pid}\photo2\\21_8.jpg")
+ if str(psid) == "29":
+ #移除指定文件
+ os.remove(f"D:\{pid}\photo1\\15_1.jpg")
+ os.remove(f"D:\{pid}\photo2\\15_8.jpg")
+ except Exception as e:
+ print("移除异常")
+
+ #旋转图片
+ os.system(f'python D:\\make2\\photo2rotate.py -w d:\ -p {pid} -i photo1 -o photo1')
+ os.system(f'python D:\\make2\\photo2rotate.py -w d:\ -p {pid} -i photo2 -o photo2')
+
+ os.system(f'python D:\\make2\\export_build_info\\gen_xmps_for_build_info.py {pid}')
+ #print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} 图片下载完成,共费时{libs.diff_time(start_time)}')
+ os.system(f'python main_step2.py {pid}')
+ # start_time = time.time()
+ # # TODO: 上报图片采集数量,更新影棚相机状态
+
+ # # 处理图片,如果experience=True,将图片缩减一半,已节省建模时间和算力成本
+ # # if experience:
+ # # libs.resize_photos(os.path.join(config.workdir, pid, 'photo1'))
+ # # libs.resize_photos(os.path.join(config.workdir, pid, 'photo2'))
+
+ # # 根据配置调整photo2曝光,均衡贴图亮度,可能产生photo3
+ # libs.adjust_photos(config.workdir, pid)
+
+ # # TODO: 检测模糊异常图片,上报微信通知
+ # # TODO: 处理图片,去反光算法
+
+ # # 检测图片定位点,定位异常及时上报微信通知给客服人员,人工判断是否需要重新拍摄或更换地贴。定义定位点距离,导出相机位姿信息
+ # detect_markers(psid, pid)
+
+ # # 处理图片,检测photo2中的异常图片不参与贴图,以免破坏贴图效果,默认不检测射灯异常图片,以节省算力成本
+ # if not makeloop:
+ # filter_dark_texture_image(pid)
+
+ # # 处理图片,暗部提亮,提高贴图效果
+
+ # # TODO: 处理图片,去遮挡处理,提高建模与贴图质量
+
+ # # 加入photo2,计算重建区域,导出重建区域与相机位姿配置信息
+ # # cal_reconstruction_region(psid, pid)
+
+ # print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} step1图片预处理完成,共费时{libs.diff_time(start_time)}')
+
+ # if os.path.exists(os.path.join(config.sharedir, pid)):
+ # shutil.rmtree(os.path.join(config.sharedir, pid), ignore_errors=True)
+ # shutil.copytree(os.path.join(config.workdir, pid), os.path.join(config.sharedir, pid))
+ # print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} step1任务完成,移动到共享目录')
+
+
+ # #指定photo2某些图片不参与贴图
+ # #是否不参与贴图,true 不参与贴图
+ # if isNoColorTexture == "NoColorTexture":
+ # arrNoTextureColorPics = config.noTextureColorPics
+ # if arrNoTextureColorPics is not None and len(arrNoTextureColorPics) > 0:
+ # for camcerIndex in arrNoTextureColorPics:
+ # #拼装坐标文件名称
+ # filename = os.path.join(config.sharedir, pid,"photo2",str(camcerIndex)+"_8.xmp")
+ # #判断文件是否存在
+ # if os.path.exists(filename):
+ # #存在就设置不参与贴图
+ # libs.set_photo_join_type(config.workdir, pid, 'photo2', camcerIndex, mesh='0', texture='0')
+
+
+ # #移除当前文件夹
+ # shutil.rmtree(os.path.join(config.workdir, pid))
+ # # TODO: 更新本地step1任务状态,加入step2任务队列
+ # if task_distributed_id == "":#不是分布式任务的时候就自动往下个步骤走,是分布式任务的时候就就执行当前任务
+ # if makeloop:
+ # os.system(f'python main_step2.py {pid}')
+ # else:
+ # os.system(f'python main_step2.py {pid}')
+ # # if os.path.exists(os.path.join(config.sharedir, pid)):
+ # # shutil.rmtree(os.path.join(config.sharedir, pid), ignore_errors=True)
+ # # shutil.move(os.path.join(config.workdir, pid), config.sharedir)
+
+ # # print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} step1任务完成,移动到共享目录')
+ # else:
+ # #分布式服务执行完后,需要更新任务状态,更新字表的finished_at字段
+ # main_service_db.update_task_distributed_detail({"task_distributed_id":task_distributed_id,"finished_at":time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})
+ # print("step1完成,休息6s")
+ # time.sleep(4)
+ # return
+
+
+def main(pid, experience=False, makeloop=True,task_distributed_id="",isNoColorTexture=""):
+ if pid == '0':
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 开始进入本地任务值守模式...')
+ while True:
+ # 取云端redis多个key任务,TODO:后续要改为api调用
+ experience = False
+ pid = libs_db.get_task('make_experience')
+ if pid == '':
+ time.sleep(3)
+ pid = libs_db.get_task('make')
+ if pid == '':
+ time.sleep(3)
+ continue
+ else:
+ experience = False
+ step1(pid, experience, makeloop,task_distributed_id,isNoColorTexture)
+ else:
+ step1(pid, experience, makeloop,task_distributed_id,isNoColorTexture)
+
+
+
+def is_already(pid):
+
+
+ #读取已经完成的pid
+ with open("D://make2/export_build_info/finished.txt", 'r') as f:
+ lines = f.readlines()
+ for line in lines:
+ print("line",str(line.strip()))
+ if str(pid) == str(line.strip()):
+ print("匹配成功")
+ return True
+ return False
+
+if __name__ == '__main__':
+ isNoColorTexture = ""
+ if len(sys.argv) == 2:
+ v = sys.argv[1]
+
+ #判断是否是数字
+ if v.isdigit():
+ #print(f"正在处理输入的pid-{v}")
+ main(str(v), experience=False, makeloop=False,task_distributed_id="",isNoColorTexture=isNoColorTexture)
+ else:
+ filePath = f"D://make2/export_build_info/pids/{v}.txt"
+ if not os.path.exists(filePath):
+ print(f"{filePath} 文件不存在")
+
+ strPids = ""
+ with open("D://make2/pid.text","r") as f:
+ lines = f.readlines()
+ for line in lines:
+ strPids = str(line.strip())
+
+ errPids = ""
+ with open("D://make2/errPid.text","r") as f:
+ lines = f.readlines()
+ for line in lines:
+ errPids = str(line.strip())
+
+ arrErrPids = errPids.split(",")
+
+ arrPids = strPids.split(",")
+ ii = 0
+ with open(filePath, 'r') as f:
+ lines = f.readlines()
+ for line in lines:
+ pid = str(line.strip())
+ if pid == "":
+ break
+
+ #判断是否存在了目录或者已经是处理过了
+ # tempFile = f"D://{pid}//finish.txt"
+ # if os.path.exists(tempFile):
+ # continue
+
+ if str(pid) in arrErrPids:
+ continue
+
+ if str(pid) in arrPids:
+ # print(f"已处理过{pid}")
+ ii += 1
+ continue
+
+ print(f"正在处理{pid}- 完成{ii}")
+ main(str(pid), experience=False, makeloop=False,task_distributed_id="",isNoColorTexture=isNoColorTexture)
+ ii += 1
+ print(f"已经完成-{ii}")
+
+
+ else:
+ print("cmd like python main_step1.py pid/单人/多人/双人/动物/人物")
+
+
+
+
+ # # 取云端redis任务,完成第一步的数据预处理后,将数据放入共享存储目录,将第二步任务塞入本地mysql队列
+ # # 默认循环值守,可传参数运行单一任务,以方便调试
+ # #atexit.register(common.notify,socket.gethostname()+"建模任务已经停止")
+ # # pid = '0'
+ # isNoColorTexture = ""
+ # # if len(sys.argv) == 2:
+ # # pids = sys.argv[1].split(',')
+ # # for pid in pids:
+ # already = [184219,184215,184209,184069,184059,183868,183817,183791,183613,183054,182855,182854,184206,184201,184199,184164,184087,184076,184029,184013,183993,183952,183888,183882,183824,183815,183812]
+
+ # arrPids = [184219,184215,184209,184206,184201,184199,184164,184087,184076,184069,184059,184029,184013,183993,183952,183888,183882,183868,183824,183817,183815,183812,183791,183777,183715,183705,183670,183613,183573,182974,182983,182985,182989,182997,183007,183051,183060,183054,183053,183097,183119,183108,183139,183141,183155,183163,183169,183180,183191,183196,183214,183244,183266,183278,183275,183309,183402,183422,183440,182974,182964,182958]
+ # #,182956,182916,182855,182854,182820,182787,182800,182809,182780,182772,182770,182766,182754,182742,182740,182723,182707,182647,182643,182614,182595,182563,182557,182547,182546,182538,182530,182517,182498,182478,182452,182386,182352,182285,182266,182260,182230,182224
+ # i = 0
+ # for pid in arrPids:
+ # if pid in already:
+ # continue
+ # print("正在处理-",pid)
+
+
+
+ # if is_already(str(pid)) == True:
+ # continue
+ # # i += 1
+ # # continue
+ # #写入到
+ # with open("D://make2/export_build_info/finished.txt", 'a+') as f:
+ # f.write(f"{pid}\n")
+
+ # main(str(pid), experience=False, makeloop=False,task_distributed_id="",isNoColorTexture=isNoColorTexture)
+
+ # print("已处理-",i)
+ # #exit()
+ # # if len(sys.argv) == 3:
+ # # experience = False
+ # # if sys.argv[2] == '1':
+ # # print('演示测试...')
+ # # experience = False
+ # # elif sys.argv[2] == 'NoColorTexture':
+ # # isNoColorTexture = "NoColorTexture"
+ # # pids = sys.argv[1].split(',')
+ # # for pid in pids:
+ # # main(pid, experience=experience, makeloop=False,task_distributed_id="",isNoColorTexture=isNoColorTexture)
+ # # exit()
+ # # main(pid, experience=False, makeloop=True,task_distributed_id="",isNoColorTexture=isNoColorTexture)
\ No newline at end of file
diff --git a/export_build_info/main_step2.py b/export_build_info/main_step2.py
new file mode 100644
index 0000000..148875f
--- /dev/null
+++ b/export_build_info/main_step2.py
@@ -0,0 +1,267 @@
+import os, sys, time, shutil, subprocess, shlex
+import platform
+import pyautogui as ag
+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,main_service_db,computerRecboxCenterByPoint
+import export_already_build
+redisLocal = config.redis_local
+def load_model(pid):
+ cmd = f'{config.rcbin} {config.r1["init"]} -load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}"'
+ print(cmd)
+ cmd = shlex.split(cmd)
+ res = subprocess.run(cmd)
+
+def get_rcver():
+ rcbin = '"C:\\Program Files\\Capturing Reality\\RealityCapture\\RealityCapture.exe"'
+ if os.path.getsize(rcbin[1:-1]) == 20783616:
+ return 1
+ else:
+ return 2
+
+def make3d(pid):
+ if get_rcver() == 1: # old version
+ #修改重建区域的大小
+ common.change_rcbox_s(pid,"1")
+ #获取影棚id
+ # psid = libs.getPSid(pid)
+ # if int(psid) == 80:
+ # change_rcbox_deepth(str(pid),0.03)
+ psid = libs.getPSid(pid)
+ simplify_value = 1000000 * libs.getHeadCount(pid)
+ add_photo3 = ' '
+ #判断是否存在photo3
+ if os.path.exists(os.path.join(config.workdir, pid, 'photo3')):
+ add_photo3 = ' -addFolder "' + os.path.join(config.workdir, pid, 'photo3') + '" -align -align '
+ #存在photo3 的情况下,photo2 不参与贴图
+ #遍历获取photo2 目录下的所有文件
+ directory = os.path.join(config.workdir, pid, 'photo2')
+ for root, dirs, files in os.walk(directory):
+ for file in files:
+ #判断file 是否以 _8.xmp 结尾
+ if file.endswith("_8.xmp") == False:
+ continue
+ #修改文件内容不参与贴图
+ libs.set_photo_join_type(config.workdir, pid, 'photo2', file.split("_")[0], mesh='0', texture='0')
+ else:
+ pass
+ #设置photo2参与贴图,因为有的时候贴图会黑
+ directory = os.path.join(config.workdir, pid, 'photo2')
+ for root, dirs, files in os.walk(directory):
+ for file in files:
+ #判断file 是否以 _8.xmp 结尾
+ if file.endswith("_8.xmp") == False:
+ continue
+ #修改文件内容不参与贴图
+ libs.set_photo_join_type(config.workdir, pid, 'photo2', file.split("_")[0], mesh='0', texture='1')
+
+ if get_rcver() == 1: # old version
+
+ #判断oss 上是否存在 controlpoints 文件
+ isExistPoint = common.isExistControlPointsOss(pid)
+ 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} \
+ -importControlPointsMeasurements "{os.path.join(config.workdir, pid, f"{pid}.controlPoints.csv")}" \
+ -align -exportRegistration "{os.path.join(config.workdir,"make2", "config","exportRegistration.xml")}" "{os.path.join(config.workdir, pid,str(pid)+"_align.csv")}" -save'
+
+ cmd = cmd + f' "{os.path.join(config.workdir, pid, f"{pid}_wait.rcproj")}"'
+ print(cmd)
+ cmd = shlex.split(cmd)
+ res = subprocess.run(cmd)
+ time.sleep(2)
+
+
+ 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)
+ #判断是否有 pid_1 的的值
+ print(pid+"_1")
+ if redisLocal.lpos('model:auto_distance',pid+"_1") == None:
+ continue
+ shutil.move(os.path.join(config.workdir, pid, f'{pid}_wait.rcproj'), os.path.join(config.workdir, pid, f'{pid}.rcproj'))
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 定义定位点距离完成')
+ #将 controlpoints_0.dat 文件拷贝到 oss 上作为公共的使用
+ common.uploadControlPointsOss(pid)
+
+ #最后处理掉redis中的值
+ redisLocal.lrem('model:auto_distance', 0, pid+"_1")
+ break
+ print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),"循环阻塞结束,判断是否对齐成功")
+
+
+ #查看对齐的数量
+ 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
+ cmdSmall = "-align"
+ #使用公共point文件的时候,就不能使用update , 而是要用 align
+ if isExistPoint == True:
+ cmdSmall = "-align"
+ #{config.r1["init"]}
+
+ if common.task_need_high_model(pid):
+ if str(psid) == "41" or str(psid) == "85":
+ calulate_type = "-mvs"
+ else:
+ calulate_type = '-mvsHigh'
+ else:
+ calulate_type = '-mvs'
+
+ #翻转相机的线向下
+ cmd = f'{config.rcbin} -load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" {cmdSmall} \
+ -set "sfmEnableCameraPrior=True" -align -set "sfmEnableCameraPrior=False" -align -save "{os.path.join(config.workdir, pid, f"{pid}_point.rcproj")}" '
+ cmd = shlex.split(cmd)
+ res = subprocess.run(cmd)
+ #执行完成后命令会触发导出点云的定时程序
+ while True:
+ print("判断是否导出点云文件循环阻塞开始")
+ time.sleep(3)
+ #判断是否有 pid_1 的的值
+ print(pid+"_3")
+ if redisLocal.lpos('model:auto_distance',pid+"_3") == None:
+ continue
+ shutil.move(os.path.join(config.workdir, pid, f'{pid}_point.rcproj'), os.path.join(config.workdir, pid, f'{pid}.rcproj'))
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 导出点云文件完成')
+ #最后处理掉redis中的值
+ redisLocal.lrem('model:auto_distance', 0, pid+"_3")
+ break
+
+ #处理点云文件
+ centerRcboxValue = computerRecboxCenterByPoint.boxCenter(pid)
+ if centerRcboxValue > 0:
+ print("修改中心点的坐标",centerRcboxValue)
+ #修改中心点的值
+ common.change_rcbox_center(pid,centerRcboxValue)
+
+ cmd = f'{config.rcbin} -load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" -align \
+ -set "sfmEnableCameraPrior=True" -align -set "sfmEnableCameraPrior=False" -align -setReconstructionRegion "{os.path.join(config.workdir, pid, f"{pid}.rcbox")}" \
+ {calulate_type} -modelSelectMaximalConnectedComponent -modelInvertSelection -modelRemoveSelectedTriangles -closeHoles -clean -simplify {simplify_value} -smooth -unwrap -calculateTexture -renameModel {pid} -save "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" -quit'
+ print(cmd)
+ cmd = shlex.split(cmd)
+ res = subprocess.run(cmd)
+ #保存在导出
+ # common.saveScreenImg(pid)
+ # time.sleep(1)
+ # ag.hotkey('alt', 'f4')
+ time.sleep(3)
+ #修改rcproj文件
+ flag = common.changeRcprojFile(pid)
+ if flag == False:
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} rcproj文件不存在')
+ return
+
+ #复制文件
+ shutil.copy(os.path.join(config.workdir, pid, f'{pid}.rcproj'), os.path.join(config.workdir, pid, f'{pid}_screen.rcproj'))
+ time.sleep(2)
+ #打开工程文件
+ cmd = f'{config.rcbin} -load "{os.path.join(config.workdir, pid, f"{pid}_screen.rcproj")}"'
+ cmd = shlex.split(cmd)
+ res = subprocess.run(cmd)
+
+ #创建指定文件夹
+ if not os.path.exists(os.path.join(config.workdir, pid, "output")):
+ os.makedirs(os.path.join(config.workdir, pid, "output"))
+
+ #判断output目录下是否有文件,有的话删除
+ files = os.listdir(os.path.join(config.workdir, pid, "output"))
+
+ #执行导出
+ cmd = f'{config.rcbin} -load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}"\
+ -exportModel "{pid}" "{os.path.join(config.workdir, pid, "output", f"{pid}.obj")}" "d:\\make2\\config\\ModelExportParams102.xml" -quit'
+ print(cmd)
+ cmd = shlex.split(cmd)
+ res = subprocess.run(cmd)
+
+
+
+ else: # new version
+ #判断是否要进行高精模
+ if common.task_need_high_model(pid):
+ if str(psid) == "41" or str(psid) == "85":
+ calulate_type = "calculateNormalModel"
+ else:
+ calulate_type = 'calculateHighModel'
+ else:
+ calulate_type = 'calculateNormalModel'
+
+ #创建指定文件夹
+ if not os.path.exists(os.path.join(config.workdir, pid, "output")):
+ os.makedirs(os.path.join(config.workdir, pid, "output"))
+
+ cmd = f'{config.rcbin} {config.r2["init"]} -setInstanceName {pid} \
+ -load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" \
+ -{calulate_type} \
+ -selectLargestModelComponent -invertTrianglesSelection -removeSelectedTriangles -simplify {simplify_value} -smooth -closeHoles -cleanModel -calculateTexture \
+ -save "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" \
+ -exportSelectedModel "{os.path.join(config.workdir, pid, "output", f"{pid}.obj")}" "d:\\make2\\config\\ModelExportParams.xml" -quit'# -quit
+ print(cmd)
+ cmd = shlex.split(cmd)
+ res = subprocess.run(cmd)
+
+ export_already_build.exportInfo(pid)
+ # #阻塞判断是否导出完成
+ # while True:
+ # #判断 output 目录下是否存在 三个文件
+ # files = os.listdir(os.path.join(config.workdir, pid, "output"))
+ # if len(files) >= 3:
+ # break
+
+def step2(pid,task_distributed_id=""):
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 开始建模任务step2')
+
+ #判断是否要从共享目录拷贝数据
+ if os.path.exists(os.path.join(config.sharedir, pid)) and not os.path.exists(os.path.join(config.workdir, pid)):
+ shutil.move(os.path.join(config.sharedir, pid), config.workdir)
+ else:
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 目录{os.path.join(config.sharedir, pid)}不存在,或{os.path.join(config.workdir, pid)}已存在')
+ # return
+ #最后还是要判断有没有存在目录
+ if not os.path.exists(os.path.join(config.workdir, pid)):
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 目录{os.path.join(config.workdir, pid)}不存在')
+ return
+
+ start_time = time.time()
+ make3d(pid)
+
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 建模任务step2完成,共费时{libs.diff_time(start_time)},任务已提交到step3')
+ # # 更新本地任务状态,加入step3任务队列
+ # if task_distributed_id == "":
+ # os.system(f'python d:\\make2\\main_step3.py {pid}')
+ # else:
+ # #暂时 step2 step3 一起连续执行
+ # print('step2 执行完,开始执行step3')
+ # os.system(f'python d:\\make2\\main_step3.py {pid}')
+ # main_service_db.update_task_distributed({"id":task_distributed_id,"status":2,"finished_at":time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})
+ # main_service_db.update_task_distributed_detail({"task_distributed_id":task_distributed_id,"finished_at":time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})
+ # #return
+
+def main(pid):
+ if pid == '0':
+ while True:
+ # 取本地mysql队列任务,完成第二步的建模任务
+
+ step2(pid)
+ else:
+ step2(pid)
+
+if __name__ == '__main__':
+ # 取本地mysql队列任务,完成第二步的建模任务
+ # 默认循环值守,可传参数运行单一任务,以方便调试
+ pid = '0'
+ if len(sys.argv) > 1:
+ pids = sys.argv[1].split(',')
+ for pid in pids:
+ main(pid)
+ exit()
+ main(pid)
\ No newline at end of file
diff --git a/export_build_info/manual_service.py b/export_build_info/manual_service.py
new file mode 100644
index 0000000..7f4a8fd
--- /dev/null
+++ b/export_build_info/manual_service.py
@@ -0,0 +1,185 @@
+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)
+ 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 = "1",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} photo1数量{photos1_count} 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 -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")}" {config.r["setTextureFalse"]} \
+ -addFolder "{targetFile}" -selectAllImages \
+ -detectMarkers "D:\\make2\\config\\detectMarkers.config.xml" \
+ {libs.get_defineDistances(psid)} -update -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}')
+ os.system(f'python D://make2/export_build_info/main_step2.py {pid}')
+
+
+def is_already(pid):
+
+
+ #读取已经完成的pid
+ with open("D://make2/export_build_info/finished.txt", 'r') as f:
+ lines = f.readlines()
+ for line in lines:
+ print("line",str(line.strip()))
+ if str(pid) == str(line.strip()):
+ print("匹配成功")
+ return True
+ return False
+
+if __name__ == '__main__':
+ already = [184219,184215,184209,184069,184059,183868,183817,183791,183613,183054,182855,182854,184206,184201,184199,184164,184087,184076,184029,184013,183993,183952,183888,183882,183824,183815,183812]
+
+ arrPids = [184219,184215,184209,184206,184201,184199,184164,184087,184076,184069,184059,184029,184013,183993,183952,183888,183882,183868,183824,183817,183815,183812,183791,183777,183715,183705,183670,183613,183573,182974,182983,182985,182989,182997,183007,183051,183060,183054,183053,183097,183119,183108,183139,183141,183155,183163,183169,183180,183191,183196,183214,183244,183266,183278,183275,183309,183402,183422,183440,182974,182964,182958,182956,182916,182855,182854,182820,182787,182800,182809,182780,182772,182770,182766,182754,182742,182740,182723,182707,182647,182643,182614,182595,182563,182557,182547,182546,182538,182530,182517,182498,182478,182452,182386,182352,182285,182266,182260,182230,182224]
+ for pid in arrPids:
+ if pid in already:
+ continue
+ print("正在处理-",pid)
+
+
+
+ if is_already(str(pid)) == True:
+ continue
+ # i += 1
+ # continue
+ #写入到
+ with open("D://make2/export_build_info/finished.txt", 'a+') as f:
+ f.write(f"{pid}\n")
+
+
+ cmd_run(str(pid),usePhoto = "1",lock=False)
+
+ # 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)
\ No newline at end of file
diff --git a/export_build_info/pids/人物.txt b/export_build_info/pids/人物.txt
new file mode 100644
index 0000000..b02645c
--- /dev/null
+++ b/export_build_info/pids/人物.txt
@@ -0,0 +1,27 @@
+181561
+181559
+180990
+180772
+180538
+180256
+179927
+179657
+179627
+178838
+178714
+178616
+178604
+178332
+177920
+176655
+184102
+183728
+183538
+183524
+183274
+183316
+183345
+182867
+182658
+182638
+182560
diff --git a/export_build_info/pids/动物.txt b/export_build_info/pids/动物.txt
new file mode 100644
index 0000000..58a4003
--- /dev/null
+++ b/export_build_info/pids/动物.txt
@@ -0,0 +1,28 @@
+181307
+181287
+181267
+180402
+179617
+179613
+178991
+178892
+178814
+178787
+178471
+178469
+178400
+178156
+177899
+177894
+176236
+184133
+184039
+183848
+183769
+183637
+183127
+183238
+182450
+182031
+181977
+181960
diff --git a/export_build_info/pids/单人.txt b/export_build_info/pids/单人.txt
new file mode 100644
index 0000000..cef740f
--- /dev/null
+++ b/export_build_info/pids/单人.txt
@@ -0,0 +1,393 @@
+181763
+181757
+181754
+181687
+181652
+181642
+181619
+181597
+181574
+181542
+181526
+181515
+181482
+181435
+181421
+181408
+181391
+181388
+181367
+181333
+181329
+181327
+181304
+181274
+181261
+181257
+181248
+181232
+181231
+181229
+181205
+181204
+181203
+181202
+181191
+181188
+181177
+181176
+181145
+181143
+181139
+181117
+181115
+181108
+181097
+181062
+181050
+181046
+181040
+181039
+181023
+181020
+180961
+180958
+180944
+180943
+180904
+180903
+180869
+180864
+180862
+180846
+180839
+180819
+180781
+180776
+180771
+180770
+180670
+180661
+180648
+180593
+180591
+180588
+180581
+180461
+180455
+180450
+180429
+180424
+180394
+180327
+180314
+180308
+180297
+180292
+180291
+180281
+180273
+180225
+180185
+180167
+180156
+180145
+180125
+180085
+180084
+180082
+179980
+179978
+179975
+179942
+179935
+179895
+179861
+179850
+179849
+179815
+179722
+179704
+179695
+179688
+179676
+179652
+179646
+179623
+179621
+179585
+179555
+179551
+179493
+179489
+179474
+179471
+179470
+179461
+179457
+179451
+179430
+179355
+179344
+179331
+179316
+179282
+179229
+179226
+179219
+179205
+179204
+179166
+179160
+179151
+179149
+179147
+179139
+178752
+178743
+178677
+178675
+178674
+178624
+178606
+178594
+178591
+178528
+178526
+178521
+178520
+178519
+178493
+178457
+178452
+178447
+178390
+178388
+178369
+178364
+178349
+178348
+178347
+178330
+178319
+178303
+178302
+178294
+178287
+178269
+178236
+178220
+178219
+178214
+178203
+178191
+178187
+178164
+178159
+178129
+178100
+178098
+178054
+178051
+178048
+178042
+178034
+178016
+177467
+177465
+177453
+177449
+177447
+177443
+177431
+177430
+177412
+177360
+177353
+177350
+177337
+177327
+177309
+178008
+177999
+177998
+177992
+177991
+177984
+177973
+177972
+177971
+177948
+177852
+177830
+177820
+177812
+177763
+177706
+177681
+177659
+177648
+177647
+177641
+177628
+177613
+177611
+177550
+177293
+177288
+177280
+177277
+177265
+177262
+177257
+177225
+177213
+177198
+177172
+177159
+177146
+177152
+177108
+177095
+177092
+177048
+177046
+177035
+176822
+176752
+176739
+176688
+176678
+176631
+176609
+176602
+176525
+176338
+176333
+176314
+176305
+176249
+176238
+184219
+184215
+184209
+184206
+184201
+184199
+184164
+184087
+184076
+184069
+184059
+184029
+184013
+183993
+183952
+183888
+183882
+183868
+183824
+183817
+183815
+183812
+183791
+183777
+183715
+183705
+183670
+183613
+183573
+182974
+182983
+182985
+182989
+182997
+183007
+183051
+183060
+183054
+183053
+183097
+183119
+183108
+183139
+183141
+183155
+183163
+183169
+183180
+183191
+183196
+183214
+183244
+183266
+183278
+183275
+183309
+183402
+183422
+183440
+182974
+182964
+182958
+182956
+182916
+182855
+182854
+182820
+182787
+182800
+182809
+182780
+182772
+182770
+182766
+182754
+182742
+182740
+182723
+182707
+182647
+182643
+182614
+182595
+182563
+182557
+182547
+182546
+182538
+182530
+182517
+182498
+182478
+182452
+182386
+182352
+182285
+182266
+182260
+182230
+182224
+182223
+182191
+182185
+182182
+182179
+182106
+182101
+182072
+181966
+181965
+181937
+181928
+181925
+181924
+181923
+181900
+181895
+181860
+181847
+181836
+181833
+181811
+181809
diff --git a/export_build_info/pids/双人.txt b/export_build_info/pids/双人.txt
new file mode 100644
index 0000000..7be7926
--- /dev/null
+++ b/export_build_info/pids/双人.txt
@@ -0,0 +1,307 @@
+181593
+181384
+181337
+181318
+181263
+181240
+181211
+181197
+181187
+181140
+181103
+181091
+181054
+181027
+180763
+180690
+180684
+180677
+180599
+180576
+180389
+180342
+180337
+180277
+180265
+180253
+180101
+180083
+179905
+179842
+179811
+179808
+179791
+179786
+179700
+179634
+179593
+179576
+179485
+179459
+179400
+179351
+178995
+178898
+178750
+178746
+178723
+178680
+178673
+178654
+178527
+178482
+178465
+178430
+178413
+178409
+178297
+178286
+178281
+178105
+178062
+178026
+178025
+178019
+178017
+178004
+177851
+177678
+177677
+177646
+177545
+177520
+177300
+177080
+176757
+176743
+176648
+176290
+176280
+176273
+176247
+184082
+184074
+184068
+184061
+184041
+183893
+183890
+183810
+183755
+183680
+183656
+183592
+183591
+183589
+183025
+183086
+183104
+183162
+183444
+182907
+182915
+182871
+182804
+182778
+182718
+182675
+182664
+182625
+182623
+182542
+182510
+182473
+182455
+182388
+182365
+182343
+182316
+181957
+181948
+181941
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/export_build_info/pids/多人.txt b/export_build_info/pids/多人.txt
new file mode 100644
index 0000000..a12d04f
--- /dev/null
+++ b/export_build_info/pids/多人.txt
@@ -0,0 +1,28 @@
+180891
+180673
+180584
+180468
+180164
+180091
+179992
+179962
+178627
+178416
+178255
+178066
+177983
+177722
+183832
+183677
+183183
+183351
+183361
+183360
+182853
+182715
+182630
+182367
+182253
+182057
+181868
+181856
diff --git a/export_build_info/registration_export_config.xml b/export_build_info/registration_export_config.xml
new file mode 100644
index 0000000..6bd1c35
--- /dev/null
+++ b/export_build_info/registration_export_config.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/export_build_info/task_distributed_error.log b/export_build_info/task_distributed_error.log
new file mode 100644
index 0000000..e69de29
diff --git a/install.txt b/install.txt
new file mode 100644
index 0000000..0dc7a86
--- /dev/null
+++ b/install.txt
@@ -0,0 +1,13 @@
+pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
+pip config set install.trusted-host pypi.tuna.tsinghua.edu.cn
+
+python -m pip install --upgrade pip
+pip install oss2 redis MySQLdb pillow numpy opencv-python bpy tqdm pyautogui psutil pywin32 pymysql
+
+
+config
+set bin="C:\Program Files\Capturing Reality\RealityCapture\RealityCapture.exe"
+%bin% -disableOnlineCommunication -setInstanceName %pid%
+%bin% -disableOnlineCommunication -delegateTo %pid%
+%bin% -set "appCacheLocation=ProjectFolder"
+
diff --git a/libs/config.py b/libs/config.py
index 74a209f..fde509a 100644
--- a/libs/config.py
+++ b/libs/config.py
@@ -49,6 +49,15 @@ mysql_dong = {
"charset": "utf8mb4"
}
+mysql_task_rc = {
+ "host": '172.31.1.254',#"172.16.20.13",
+ "port": 23306,
+ "user": "pi",
+ "password": "ph2008",
+ "db": "suwa3d",
+ "charset": "utf8mb4"
+}
+
if platform.system() == 'Windows':
workdir = 'D:\\'
sharedir = 'E:\\'
@@ -115,7 +124,7 @@ r2 = {
#new_make_psids = ['1', '17', '29', '44', '54', '55', '63', '65', '77', '79', '80', '85', '86']
#企业微信通知人员
-notify_user_Ids = ["DongZhangXi","YouShui"]
+notify_user_Ids = ["DongZhangXi"]
#任务运行超时时间设定 ,单位秒
task_run_timeout = {
diff --git a/libs/libs.py b/libs/libs.py
index 9489503..d8950b1 100644
--- a/libs/libs.py
+++ b/libs/libs.py
@@ -330,4 +330,52 @@ def down_obj_from_oss_for_fix(workdir, pid, action):
# print('正在下载:', file.key)
localfile = os.path.join(workdir, action, pid, filename)
config.oss_bucket.get_object_to_file(file.key, localfile)
- return obj_filename
\ No newline at end of file
+ return obj_filename
+
+def down_obj_from_oss_for_repeat_texture(workdir, pid, action):
+ print(os.path.join(workdir, pid))
+ if not os.path.exists(os.path.join(workdir, pid)):
+ print("目录不存在,无法处理")
+ return "error"
+
+ #判断是否有专门新建的目录用来重新贴图
+ newPath = os.path.join(workdir, pid,'repeat_texture','completion_cloud')
+ if not os.path.exists(newPath):
+ os.makedirs(newPath)
+
+
+ # 根据前缀获取文件列表
+ prefix = f'objs/{action}/{pid}/ai/repeat_texture/completion_cloud'
+ filelist = oss2.ObjectIteratorV2(config.oss_bucket, prefix=prefix)
+ print('正在下载:', prefix)
+ for file in filelist:
+ filename = file.key.split('/')[-1]
+ if filename == "":
+ continue
+ localfile = os.path.join(newPath, filename)
+ config.oss_bucket.get_object_to_file(file.key, localfile)
+ return newPath
+
+
+
+
+def down_obj_from_oss_auto(pid,action,pathStr):
+ #pathStr = os.path.join(workdir, str(pid)+"_ai")
+ if not os.path.exists(pathStr):
+ os.makedirs(pathStr)
+
+ # 根据前缀获取文件列表
+ prefix = f'objs/{action}/{pid}'
+ filelist = oss2.ObjectIteratorV2(config.oss_bucket, prefix=prefix)
+ print('正在下载:', prefix)
+ for file in filelist:
+ filename = file.key.split('/')[-1]
+ if filename == "":
+ continue
+
+ if filename != f"{pid}.jpg" and filename != f"{pid}.obj" and filename != f"{pid}.mtl":
+ continue
+
+ print(filename)
+ localfile = os.path.join(pathStr, filename)
+ config.oss_bucket.get_object_to_file(file.key, localfile)
\ No newline at end of file
diff --git a/libs/libs_db_repeat_texture.py b/libs/libs_db_repeat_texture.py
new file mode 100644
index 0000000..00d522e
--- /dev/null
+++ b/libs/libs_db_repeat_texture.py
@@ -0,0 +1,83 @@
+# mysql数据库常用任务函数封装
+import pymysql, socket, time
+import config
+
+#公共连接库
+def pymysqlAlias():
+ return pymysql.connect(
+ host=config.mysql_gpu['host'],
+ port=config.mysql_gpu['port'],
+ user=config.mysql_gpu['user'],
+ password=config.mysql_gpu['password'],
+ db=config.mysql_gpu['db'],
+ charset=config.mysql_gpu['charset'],)
+
+
+
+# 新增新的任务
+def add_reapeat_texture_task(data):
+ try:
+
+ resExist = is_exist(data["pid"])
+ if resExist == True:
+ return
+
+ with pymysqlAlias() as conn:
+ cursor = conn.cursor()
+ sql = f'insert into task_repeat_texture (pid,heads,createTime) values ("{data["pid"]}","{data["heads"]}","{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}")'
+ 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)}")
+
+
+#
+def is_exist(pid):
+ try:
+ with pymysqlAlias() as conn:
+ cursor = conn.cursor()
+ sql = f'select count(*) from task_repeat_texture where pid = {pid} and status = 0'
+ 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 get_pid_task():
+ try:
+ with pymysqlAlias() as conn:
+ cursor = conn.cursor()
+ sql = f'select * from task_repeat_texture where status = 1 limit 1'
+ print(f'sql: {sql}')
+ cursor.execute(sql)
+ result = cursor.fetchone()
+ if result:
+ return result
+ else:
+ return None
+ except Exception as e:
+ print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())} 执行get_pid_task()异常: {str(e)}")
+ return "error"
+
+
+
+#更新状态
+def update_status(id,status):
+ try:
+ with pymysqlAlias() as conn:
+ cursor = conn.cursor()
+
+ hostname = socket.gethostname()
+ sql = f'update task_repeat_texture set status = {status},updateTime = now() where id = {id}'
+ 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_status()异常: {str(e)}")
\ No newline at end of file
diff --git a/libs/libs_db_task_rc.py b/libs/libs_db_task_rc.py
new file mode 100644
index 0000000..087e5cc
--- /dev/null
+++ b/libs/libs_db_task_rc.py
@@ -0,0 +1,30 @@
+# mysql数据库常用任务函数封装
+import pymysql, socket, time
+import config
+
+#公共连接库
+def pymysqlAlias():
+ return pymysql.connect(
+ host=config.mysql_task_rc['host'],
+ port=config.mysql_task_rc['port'],
+ user=config.mysql_task_rc['user'],
+ password=config.mysql_task_rc['password'],
+ db=config.mysql_task_rc['db'],
+ charset=config.mysql_task_rc['charset'],)
+
+# 获取新的任务
+def get_task_rc_count():
+ try:
+ with pymysqlAlias() as conn:
+ cursor = conn.cursor()
+ sql = f'select count(*) from task_distributed where status != 2 and created_at >= "2024-09-02 00:00:00"'
+ # 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_rc_count()异常: {str(e)}")
+ return ''
\ No newline at end of file
diff --git a/main_repeat_texture.py b/main_repeat_texture.py
new file mode 100644
index 0000000..cbfd5ad
--- /dev/null
+++ b/main_repeat_texture.py
@@ -0,0 +1,101 @@
+#读取需要重新贴图的数据
+import os,sys,time,shlex,subprocess,shutil
+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 libs_db_repeat_texture
+import libs,config
+
+
+#读取 数据库的信息
+def get_pid():
+ data = libs_db_repeat_texture.get_pid_task()
+ if data != None and data != "error":
+ return data[0],data[1]
+ else:
+ return None,None
+
+#开始处理任务
+def start_task(pid):
+ #下载Obj数据
+ print(f"处理{pid}任务")
+ print("开始下载{pid}数据")
+ # pid = str("175635")
+ complateCloudPath = libs.down_obj_from_oss_for_repeat_texture(config.workdir, pid,"auto")
+ if complateCloudPath == "error":
+ return -1,"error-从oss上下载出问题"
+ #下载下来之后重新加载obj 和texture
+ print("complateCloudPath",complateCloudPath)
+
+
+ outPath = os.path.join(config.workdir, pid, "output")
+ if os.path.exists(outPath):
+ print("移除文件夹")
+ #移除文件夹
+ shutil.rmtree(outPath)
+
+ cmd = f'{config.rcbin} {config.r2["init"]} -setInstanceName {pid} \
+ -load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" \
+ -importModel "{os.path.join(complateCloudPath, f"{pid}.obj")}" \
+ -calculateTexture -exportSelectedModel "{os.path.join(config.workdir, pid, "output", f"{pid}.obj")}" "d:\\make2\\config\\ModelExportParams0722.xml" -quit'
+ print(cmd)
+ cmd = shlex.split(cmd)
+ res = subprocess.run(cmd)
+
+ #检查out目录文件夹是否有多个 贴图文件。如果是的话只保留最新的一个,并且重命名为初始图像的名称
+ outFilePath = os.path.join(config.workdir, pid, "output")
+ arrTempImage = []
+ for file in os.listdir(outFilePath):
+ if file.endswith(".jpg") or file.endswith(".png"):
+ #字符串替换
+ fileTempName = file.replace(f"{pid}_u0_v0_diffuse","")
+ fileTempName = fileTempName.replace(".jpg","")
+ fileTempName = fileTempName.replace(".png","")
+ if "_" in fileTempName:
+ fileTempName = fileTempName.replace("_","")
+ arrTempImage.append(fileTempName)
+ print(arrTempImage)
+ if len(arrTempImage) > 1:
+ #获取 arrTempImage 中最大的值
+ arrTempImage.sort()
+ print(arrTempImage)
+ #获取最大值
+ maxValue = arrTempImage[-1]
+
+ for i in arrTempImage:
+ if i == "":
+ filePath1 = os.path.join(config.workdir, pid, "output",pid+"_u0_v0_diffuse.jpg")
+ filePath2 = os.path.join(config.workdir, pid, "output",pid+"_u0_v0_diffuse.png")
+ else:
+ filePath1 = os.path.join(config.workdir, pid, "output",pid+"_u0_v0_diffuse_"+str(i)+".jpg")
+ filePath2 = os.path.join(config.workdir, pid, "output",pid+"_u0_v0_diffuse_"+str(i)+".png")
+
+ if i != maxValue:
+ if os.path.exists(filePath1):
+ os.remove(filePath1)
+ if os.path.exists(filePath2):
+ os.remove(filePath2)
+ else:
+ if os.path.exists(filePath1):
+ os.rename(filePath1,os.path.join(config.workdir, pid, "output",pid+"_u0_v0_diffuse.jpg"))
+ if os.path.exists(filePath2):
+ os.rename(filePath2,os.path.join(config.workdir, pid, "output",pid+"_u0_v0_diffuse.jpg"))
+ #执行step3
+ os.system(f'python d:\\make2\\main_step3.py {pid}')
+ return 3,"success"
+
+if __name__ == '__main__':
+ while True:
+ id,pid = get_pid()
+ print(f"读取的数据{pid}")
+ if pid != None:
+ #更新状态为2
+ libs_db_repeat_texture.update_status(id,2)
+ statusres,res = start_task(str(pid))
+ libs_db_repeat_texture.update_status(id,statusres)
+ else:
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}-没有任务')
+ time.sleep(10)
diff --git a/main_step1.py b/main_step1.py
index 62f9240..842053a 100644
--- a/main_step1.py
+++ b/main_step1.py
@@ -110,16 +110,14 @@ def step1(pid, experience=False, makeloop=True,task_distributed_id="",isNoColorT
libs.down_from_oss(config.oss_bucket, config.workdir, pid)
try:
if str(psid) == "86":
- #移除指定文件
os.remove(f"D:\{pid}\photo1\\21_1.jpg")
os.remove(f"D:\{pid}\photo2\\21_8.jpg")
+
if str(psid) == "29":
- #移除指定文件
os.remove(f"D:\{pid}\photo1\\15_1.jpg")
os.remove(f"D:\{pid}\photo2\\15_8.jpg")
except Exception as e:
- print("移除异常")
-
+ print("移除照片异常")
os.system(f'python tools/downxmps.py {pid}')
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} 图片下载完成,共费时{libs.diff_time(start_time)}')
diff --git a/main_step2.py b/main_step2.py
index 9da8c28..6e2746c 100644
--- a/main_step2.py
+++ b/main_step2.py
@@ -1,12 +1,13 @@
import os, sys, time, shutil, subprocess, shlex
import platform
import pyautogui as ag
+from export_build_info import export_already_build
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,main_service_db,computerRecboxCenterByPoint
+import config, libs, libs_db,common,main_service_db,computerRecboxCenterByPoint,libs_db_repeat_texture
redisLocal = config.redis_local
def load_model(pid):
cmd = f'{config.rcbin} {config.r1["init"]} -load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}"'
@@ -216,6 +217,16 @@ def make3d(pid):
if len(files) >= 3:
break
+ # #插入需要重新贴图的任务表
+ # libs_db_repeat_texture.add_reapeat_texture_task({"pid":pid,"heads":libs.getHeadCount(pid)})
+ # #然后将导出的obj文件上传到oss上
+ # config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/ai/repeat_texture/{pid}.obj', os.path.join(config.workdir, pid, 'output', f'{pid}.obj'))
+ # config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/ai/repeat_texture/{pid}.mtl', os.path.join(config.workdir, pid, 'output', f'{pid}.mtl'))
+ # config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/ai/repeat_texture/{pid}_u0_v0_diffuse.jpg', os.path.join(config.workdir, pid, 'output', f'{pid}_u0_v0_diffuse.jpg'))
+ # config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/ai/repeat_texture/{pid}.obj.rcInfo', os.path.join(config.workdir, pid, 'output', f'{pid}.obj.rcInfo'))
+ # #导出建模信息
+ export_already_build.exportInfo(str(pid))
+
def step2(pid,task_distributed_id=""):
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 开始建模任务step2')
diff --git a/main_step3.py b/main_step3.py
index 38c4dd5..87b4846 100644
--- a/main_step3.py
+++ b/main_step3.py
@@ -206,13 +206,11 @@ def step3(pid,task_distributed_id=""):
export_and_update_obj(pid)
resize_texture_and_reload_obj(pid)
export_and_update_glbs(pid)
+ #向gpu服务器数据库添加一条数据用于AI自动修模,目前显示修复脸,不能上传更新建模状态,防止任务进入到修模部,人数为1才进行处理
+ headCount = libs.getHeadCount(pid)
+ #if headCount == 1:
+ libs_db_gpu.add_task(data={"pid":pid,"cut_body":"face","heads":headCount})
- #向gpu数据库task 插入任务,用于开始执行AI修模
- headcount = libs.getHeadCount(pid)
- #if headcount == 1:
- libs_db_gpu.add_task(data={"pid":pid,"cut_body":"face","heads":headcount})
-
-
# 更新本地任务状态,更新云端任务状态
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 模型后道处理完成,共费时{libs.diff_time(start_time)}')
res = requests.post(config.urls['update_status_modelsuccess_url'], data={'id': pid})
@@ -228,6 +226,12 @@ def step3(pid,task_distributed_id=""):
print("step3 已执行完成")
#return
common.removeFolder(str(pid))
+
+ os.system(f"python D:/make2/tools/get_weight_by_pid.py {pid}")
+ #执行模型优化,异步调用,再ai_repair 服务区上执行
+ os.system(f"python D://make2/tools/optimize_model/main.py {pid}")
+
+
def main(pid):
if pid == '0':
while True:
diff --git a/manual_service.py b/manual_service.py
index f3dae79..8aef172 100644
--- a/manual_service.py
+++ b/manual_service.py
@@ -68,7 +68,7 @@ def cmd_run(pid,usePhoto = "1",lock=False):
-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 -align -align \
+ -align -align \
{exportxmp} \
-save "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" -quit'
print(cmd)
@@ -90,8 +90,6 @@ def cmd_run(pid,usePhoto = "1",lock=False):
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):
@@ -107,7 +105,7 @@ def cmd_run(pid,usePhoto = "1",lock=False):
-load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" {config.r["setTextureFalse"]} \
-addFolder "{targetFile}" -selectAllImages \
-detectMarkers "D:\\make2\\config\\detectMarkers.config.xml" \
- {libs.get_defineDistances(psid)} -update -align -align -align -align {config.r2["setRegion"]} \
+ {libs.get_defineDistances(psid)} -update -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 \
diff --git a/manual_single.py b/manual_single.py
index 7d15497..c84220b 100644
--- a/manual_single.py
+++ b/manual_single.py
@@ -61,7 +61,7 @@ def cmd_run(pid,usePhoto = "2",lock=False):
else:
exportxmp = ' -exportXMP "D:\\make2\\config\\exportXMP.config.xml" '
- usePhoto = "photo"+str(usePhoto)
+ usePhoto = "photo2"
#执行命令
cmd = f'{config.rcbin} {config.r2["init"]} -setInstanceName "{pid}" \
@@ -104,7 +104,7 @@ def cmd_run(pid,usePhoto = "2",lock=False):
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 {config.r2["setRegion"]} \
+ {libs.get_defineDistances(psid)} -update -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 \
diff --git a/pid.text b/pid.text
new file mode 100644
index 0000000..bf2b155
--- /dev/null
+++ b/pid.text
@@ -0,0 +1,499 @@
+189002
+189819
+190152
+190141
+190204
+190210
+190221
+190234
+190257
+190264
+190297
+190377
+190238
+190409
+190417
+190144
+190233
+189879
+190227
+190463
+190510
+190531
+164671
+190241
+190547
+188521
+190609
+184467
+188521
+189772
+188521
+190724
+190506
+190509
+190511
+190578
+183895
+190584
+190605
+190611
+190620
+190635
+190683
+190684
+190694
+190697
+190708
+190726
+183494
+185507
+188521
+183494
+190751
+183895
+190754
+183895
+189002
+190784
+190783
+190795
+190812
+183895
+190823
+190837
+190910
+190838
+190866
+190905
+190915
+190927
+190944
+190939
+190932
+190379
+190948
+190959
+190980
+190975
+190927
+190996
+190981
+191001
+190927
+190992
+182361
+185080
+191045
+185416
+191069
+191082
+191081
+191103
+191118
+191116
+191152
+191180
+191125
+191227
+191238
+191246
+191234
+191275
+191320
+191283
+191354
+191388
+191435
+191441
+191431
+191380
+191340
+191350
+191297
+191472
+191255
+191268
+191501
+191192
+191156
+191517
+191515
+191525
+191532
+191261
+191422
+191024
+191542
+191587
+191597
+191676
+191678
+191711
+191736
+186628
+191874
+191937
+191924
+191945
+191887
+191868
+191981
+191885
+191838
+191882
+191965
+191822
+191870
+191920
+191894
+191811
+191739
+191681
+191790
+191738
+191699
+191781
+191733
+191746
+191793
+191829
+191834
+191907
+191927
+191969
+191990
+191998
+192005
+192021
+192023
+192026
+191771
+190829
+192038
+191906
+192095
+192107
+192098
+192123
+191066
+192150
+192161
+192178
+191210
+191849
+191832
+192093
+192199
+192208
+192202
+192213
+192211
+192204
+183783
+192220
+192267
+192223
+190880
+192288
+188877
+192283
+192291
+192079
+192077
+192072
+192063
+188201
+192343
+192353
+192367
+192373
+192222
+192399
+192392
+189979
+189988
+189996
+190692
+190709
+191955
+191912
+192444
+192438
+187727
+192479
+192473
+192469
+192476
+192140
+192143
+192158
+192498
+192169
+192175
+192186
+192187
+192197
+192214
+190362
+192236
+192239
+192241
+192242
+192244
+192248
+192304
+192261
+192421
+192425
+192514
+192162
+192548
+192550
+184779
+192495
+192490
+192583
+192586
+192591
+192593
+192595
+184756
+192235
+187195
+192378
+192622
+192129
+192570
+192566
+192480
+192481
+192484
+192482
+192532
+192624
+192630
+192682
+192674
+192690
+192701
+188185
+192725
+192729
+192608
+192732
+192717
+192609
+192611
+192612
+192615
+192744
+192643
+192650
+192653
+192659
+192776
+192664
+192676
+192680
+192758
+192759
+192767
+192775
+192782
+192783
+185658
+192838
+192873
+192875
+192905
+192895
+192869
+187718
+188167
+192929
+192940
+192955
+192947
+192907
+192908
+192887
+192979
+193038
+193003
+193005
+192875
+193112
+193101
+193085
+193082
+192986
+192944
+193132
+193141
+193058
+193160
+193074
+193217
+193239
+192208
+193285
+193260
+193287
+193288
+193298
+193281
+193335
+193332
+193349
+193165
+193185
+193010
+193231
+193364
+193295
+193313
+193339
+193354
+193357
+193360
+193375
+193376
+193377
+193378
+193353
+193193
+193454
+192317
+193405
+193468
+193475
+193483
+193479
+193486
+193508
+193504
+193511
+193503
+193520
+193562
+193571
+193560
+193237
+193569
+193591
+193590
+193593
+193617
+193615
+193637
+193625
+193642
+193646
+193683
+193671
+193677
+193616
+193702
+193700
+193604
+193721
+193745
+193770
+193768
+193758
+193762
+193636
+193652
+190141
+193771
+193781
+193813
+193806
+193812
+193818
+193835
+193863
+193907
+193832
+193896
+193903
+193906
+193380
+193383
+193384
+193925
+193386
+193480
+193387
+193666
+193711
+193757
+193934
+193778
+193795
+193809
+193822
+193817
+193843
+193918
+193876
+193922
+193567
+193564
+193551
+192320
+193117
+193961
+193969
+193524
+193547
+193990
+193995
+194012
+194022
+194027
+194021
+194069
+194048
+194035
+194070
+194015
+194018
+194093
+194098
+194144
+194104
+194112
+194119
+194108
+194126
+194153
+194163
+194044
+194047
+194206
+194004
+194229
+194218
+194240
+194242
+194278
+194271
+194293
+194081
+194173
+194176
+194211
+194245
+194270
+194285
+194292
+194294
+194296
+194300
+194347
+190480
+190483
+194258
+194266,194276,194444,194419,194454,194471,194470,194473,194475,194480,194493,194497,194499,194480,194460,192716,194465,194514,194515,194527,194501,194500,194526,194531,194536,194540,194551,194564,194577,194582,194580,187324,194599,194601,194628,194625,194623,189048,186982,194627,194508,194510,189048,194640,194642,194654,194685,194686,194707,194720,194719,194744,194734,194634,194738,194760,194765,194764,194768,194774,190697,194566,194356,194365,194369,194806,194376,194064,194772,194097,194773,194100,194103,194812,194810,194223,194181,194178,194589,194588,186685,194831,194830,194832,194834,194854,194817,194878,191283,191321,194900,194904,194858,194901,194885,194916,194924,194925,194802,194927,194932,194906,194908,194911,194912,194914,194915,194917,194920,194953,194926,194928,194930,194935,194957,194817,190531,189819,194989,194987,194995,194996,192305,194998,195015,195013,195023,195018,195021,195032,195005,195050,189864,195067,195072,195091,195026,195031,195104,195029,195102,195051,195063,195093,195125,195146,193800,195160,195172,195154,195184,194210,186610,191005,187854,193794,
\ No newline at end of file
diff --git a/step.text b/step.text
new file mode 100644
index 0000000..f68ca32
--- /dev/null
+++ b/step.text
@@ -0,0 +1,5 @@
+old version
+
+init:
+
+ '"C:\\Program Files\\Capturing Reality\\RealityCapture\\RealityCapture.exe" -disableOnlineCommunication -set \"sfmEnableCameraPrior=False\" -set \"sfmMaxFeaturesPerMpx=20000\" -set \"sfmMaxFeaturesPerImage=200000\" -set \"sfmImagesOverlap=High\" -set \"sfmMaxFeatureReprojectionError=1\" -addFolder "D:\\{pid}\\photo1" -addFolder "D:\\{pid}\\photo2" -importControlPointsMeasurements "D:\\{pid}\\{pid}..controlPoints.csv" -align -save'
\ No newline at end of file
diff --git a/suwa_cut_foot_cut_normal_data.txt b/suwa_cut_foot_cut_normal_data.txt
new file mode 100644
index 0000000..678ca37
--- /dev/null
+++ b/suwa_cut_foot_cut_normal_data.txt
@@ -0,0 +1,1028 @@
+24940
+68906
+88630
+88577
+97498
+71421
+87608
+8171
+78384
+6997
+86851
+98679
+86508
+89740
+85599
+94736
+78354
+77972
+78376
+16920
+86395
+10074
+99642
+11797
+49366
+84827
+85974
+44784
+99994
+40869
+55887
+82481
+89063
+88616
+86500
+70532
+98474
+94109
+15707
+87872
+85838
+90422
+86171
+11997
+115116
+113276
+95446
+86246
+88628
+47645
+82455
+117658
+70740
+83983
+89694
+87049
+87163
+33899
+90469
+87975
+86075
+29805
+128193
+87550
+85362
+86502
+86330
+90227
+115220
+89919
+90425
+104867
+86584
+90132
+113019
+13073
+10873
+12171
+86890
+90903
+24772
+136305
+79333
+87745
+89431
+86146
+124091
+49934
+50221
+87912
+87084
+87516
+86424
+88116
+97615
+85963
+94817
+82435
+41537
+44781
+89199
+89727
+62516
+87565
+87268
+115194
+82190
+89120
+89563
+65653
+47053
+88046
+92424
+88481
+86349
+53638
+88617
+88445
+88205
+88355
+59322
+90448
+18252
+78351
+29507
+86428
+89783
+86035
+46352
+90406
+90843
+7126
+90148
+86279
+101042
+73988
+88836
+90369
+79755
+86673
+33247
+88524
+39732
+43054
+42595
+87737
+87271
+87451
+80007
+88221
+88686
+86275
+71321
+98878
+71422
+86497
+107527
+52884
+88241
+90589
+83068
+90447
+87596
+29796
+87439
+25048
+87168
+29888
+24941
+68508
+90209
+20197
+86443
+94857
+64004
+87848
+88369
+86496
+88590
+30033
+88475
+87861
+88253
+88983
+57762
+87416
+86552
+91177
+86734
+86490
+87954
+88772
+49404
+7814
+86425
+89596
+58122
+27534
+86347
+50160
+89579
+82700
+55026
+99989
+85710
+87095
+16089
+88591
+39662
+91180
+98714
+86419
+125464
+85715
+55030
+91183
+86383
+109374
+78448
+55730
+86435
+21780
+90151
+88255
+66521
+54023
+87765
+90139
+14475
+115123
+87079
+77145
+88178
+22210
+98993
+87015
+88503
+20203
+36791
+125436
+48477
+12177
+86278
+89957
+122998
+46130
+71303
+93778
+24766
+40776
+41320
+42781
+86445
+83980
+75405
+55370
+88882
+78149
+87649
+87514
+85939
+81419
+40943
+87901
+87235
+82486
+66531
+50007
+88374
+86709
+82496
+82511
+16076
+115114
+86833
+74624
+86857
+89107
+91185
+40884
+88509
+135848
+55011
+8547
+86112
+85794
+90052
+86078
+88918
+70756
+64088
+22152
+87635
+87290
+29427
+89364
+98674
+116852
+12172
+88827
+90439
+44779
+90088
+115132
+109445
+82483
+87818
+87873
+121685
+42047
+87052
+85912
+118440
+86503
+87175
+68349
+13084
+77142
+50370
+88563
+86495
+87037
+108109
+115122
+98091
+57168
+88507
+75408
+8610
+86949
+79125
+8776
+57204
+91173
+82696
+49327
+24942
+56654
+88359
+50027
+86300
+102719
+86446
+64142
+86611
+88627
+117356
+86454
+126409
+28921
+6970
+89024
+87887
+89621
+94967
+107145
+47890
+88093
+88995
+50342
+55018
+26695
+86338
+54400
+78385
+86820
+88968
+88573
+98996
+68697
+86331
+90551
+12335
+86511
+27553
+70729
+82408
+82571
+87906
+77221
+90600
+88629
+6968
+9023
+29770
+85788
+87390
+151860
+74411
+112909
+115378
+82125
+136885
+105856
+102508
+80095
+8164
+74708
+13024
+82623
+81145
+48218
+80514
+106158
+82563
+90603
+114365
+102402
+105871
+71141
+100610
+70831
+131590
+153149
+91115
+25043
+72000
+75773
+6983
+113196
+73463
+75572
+97938
+82044
+89072
+116130
+116192
+80466
+115416
+71842
+87966
+86513
+82793
+146462
+113922
+73438
+73711
+105016
+73412
+102759
+89036
+89971
+88871
+130972
+152817
+86507
+80759
+80706
+8141
+104590
+70200
+73444
+40947
+73470
+76324
+149080
+72970
+69739
+79145
+102141
+106243
+101876
+82100
+71758
+80770
+86906
+87477
+105343
+70279
+76230
+84057
+69633
+81580
+8140
+75622
+105490
+72923
+58586
+114159
+101076
+104459
+104628
+86672
+74833
+152986
+100841
+100025
+75045
+72792
+81921
+70599
+106421
+141436
+72135
+8124
+146818
+31596
+116457
+80996
+105102
+113518
+72976
+82434
+105171
+40913
+114432
+137257
+86995
+8200
+75689
+106671
+44786
+70475
+81564
+146161
+71404
+104561
+113937
+73392
+81532
+112984
+82748
+85998
+88038
+71089
+74118
+76108
+106324
+87291
+81026
+88947
+106337
+105794
+82705
+70888
+69593
+74327
+80415
+122616
+76396
+8253
+70885
+151841
+72077
+116187
+114307
+72260
+6963
+70596
+88712
+98868
+80312
+86746
+8199
+100005
+82282
+40948
+121880
+71508
+13121
+80683
+82181
+152309
+49325
+105360
+104984
+86989
+85502
+72199
+71100
+40816
+88272
+102239
+104128
+96956
+73389
+106465
+114158
+104528
+69644
+105650
+51431
+104418
+105344
+73597
+58190
+68680
+105439
+102687
+114697
+105104
+116598
+62515
+96436
+102542
+70455
+81528
+89710
+105088
+102753
+69898
+115929
+86115
+106738
+142193
+122293
+85774
+72306
+81554
+71067
+28769
+104130
+105979
+75466
+8121
+72095
+5875
+152573
+141587
+101283
+81261
+104849
+135470
+114587
+74989
+60247
+91151
+76329
+70638
+74981
+102295
+104957
+104164
+98858
+75392
+153167
+114890
+152766
+142029
+75523
+80002
+82209
+80822
+73382
+86491
+114166
+69258
+81891
+40814
+106078
+104489
+75411
+84820
+105702
+88514
+106753
+136880
+106066
+87307
+122608
+88545
+112911
+76105
+82123
+73125
+80407
+76014
+106220
+122735
+72975
+86065
+73474
+68786
+106129
+40876
+105802
+82428
+75508
+88593
+72337
+137362
+87354
+153039
+87155
+69892
+100718
+80127
+76237
+116521
+71539
+80519
+89530
+71209
+80743
+80209
+88184
+49361
+152218
+117178
+106310
+88006
+81729
+103216
+87615
+64126
+107188
+86128
+88363
+69714
+72203
+70355
+70530
+73472
+74368
+86509
+122599
+74410
+82382
+75609
+105768
+82204
+114197
+114035
+8160
+114335
+69639
+35645
+114821
+75491
+31191
+82752
+80518
+39410
+102707
+122205
+73744
+152421
+12089
+80470
+116398
+73799
+104680
+104090
+105620
+87996
+105287
+129944
+89201
+52051
+106177
+122650
+73924
+89570
+82139
+146823
+64996
+80812
+137281
+82722
+146064
+116528
+114299
+104391
+80510
+70527
+30034
+86860
+105699
+104122
+80037
+104458
+128547
+72248
+86073
+98860
+137373
+44775
+105390
+105251
+114203
+73217
+74383
+114565
+59610
+104870
+82614
+153162
+100015
+8145
+117625
+80998
+54403
+88128
+73437
+73356
+81920
+88417
+136185
+105697
+70889
+72957
+72798
+105035
+102468
+80208
+116546
+104933
+93707
+74685
+71461
+73976
+105426
+44755
+70349
+44794
+122619
+74027
+74687
+89184
+53139
+80362
+73128
+40781
+6847
+152106
+106473
+72070
+44836
+86482
+75052
+40772
+74560
+81985
+105876
+105872
+40925
+88682
+151995
+72783
+77974
+145908
+49345
+49357
+121936
+107178
+87188
+105039
+136716
+88327
+102747
+90704
+105445
+81824
+152098
+40771
+116999
+75374
+85743
+88804
+101599
+73257
+6991
+146466
+105273
+69771
+87506
+113497
+86325
+152423
+86680
+82792
+104109
+86694
+75019
+100675
+85944
+116503
+115524
+141188
+88936
+105609
+91175
+82512
+105750
+116176
+74197
+106625
+73722
+82082
+84064
+70300
+75272
+104911
+141385
+74925
+76101
+72419
+106094
+70336
+104460
+81258
+74097
+153236
+44788
+6965
+86684
+81211
+102194
+113844
+105642
+114395
+141141
+88852
+73738
+75501
+152182
+142162
+74784
+64155
+97494
+114781
+152500
+145528
+76106
+70120
+75377
+71840
+146105
+152498
+151840
+81701
+74702
+146669
+81450
+73291
+75446
+81590
+31599
+122287
+71129
+113123
+18505
+121624
+69765
+69160
+40882
+89268
+76339
+152775
+70255
+89076
+82749
+88239
+104140
+106382
+87864
+74679
+71551
+39413
+102313
+105728
+70171
+81476
+116582
+73045
+85612
+73820
+105007
+148909
+137185
+87283
+89413
+43059
+115968
+73451
+72205
+56408
+86706
+106597
+71633
+102466
+72763
+113774
+12088
+89584
+113944
+73467
+75788
+122605
+71093
+114190
+76328
+76387
+76213
+69770
+82046
+106083
+136017
+84730
+69133
+114523
+74074
+106342
+104548
+100735
+30336
+106086
+104142
+122523
+88697
+139439
+80290
+116574
+75114
+114416
+72223
+75518
+73939
+114359
+48250
+73049
+71535
+113667
+72169
+100824
+73262
+77232
+61802
\ No newline at end of file
diff --git a/task_distributed_error.log b/task_distributed_error.log
new file mode 100644
index 0000000..64b6397
Binary files /dev/null and b/task_distributed_error.log differ
diff --git a/test.py b/test.py
index 1498d28..c2937f0 100644
--- a/test.py
+++ b/test.py
@@ -1,15 +1,18 @@
-import psutil
+import re
-# 获取硬盘分区列表
-partitions = psutil.disk_partitions()
+def extract_o_option(file_path):
+ pattern = re.compile(r'o\s+(\S+)')
+ with open(file_path, 'r') as file:
+ for line in file:
+ match = pattern.search(line)
+ if match:
+ return match.group(1)
+ return None
-for partition in partitions:
- print("分区信息",partition)
- # 获取指定分区(比如'C:')的使用情况
- if partition.mountpoint == 'G:\\': # 更改为您要检测的硬盘分区
- usage = psutil.disk_usage(partition.mountpoint)
-
- 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}%")
\ No newline at end of file
+# 使用示例
+file_path = 'C:/Users/Administrator/Desktop/29282/29282_9cm_x1.obj'
+result = extract_o_option(file_path)
+if result:
+ print(f'Found -o option with value: {result}')
+else:
+ print('No -o option found')
diff --git a/timer/check_task.py b/timer/check_task.py
index 31eca16..a2d1657 100644
--- a/timer/check_task.py
+++ b/timer/check_task.py
@@ -158,8 +158,8 @@ def get_time_out(hostname,step):
if __name__ == '__main__':
#开启死循环
while True:
- check_task_distributed_detail()
- check_task()
+ # check_task_distributed_detail()
+ # check_task()
#两分钟检测一次
time.sleep(120)
print("检测是否存在运行时间超长的任务,进行消息通知")
diff --git a/timer/get_weight_to_update.py b/timer/get_weight_to_update.py
new file mode 100644
index 0000000..cf854da
--- /dev/null
+++ b/timer/get_weight_to_update.py
@@ -0,0 +1,74 @@
+import redis,time,requests,json,os
+
+
+def getOrderInfoByOrderId(orderId):
+ try:
+
+ url = "https://mp.api.suwa3d.com/api/physical/infoModelSizeByOrderId?order_id="+str(orderId)
+ print("url:",url)
+ res = requests.get(url)
+ if res.status_code != 200:
+ print('获取失败,程序退出')
+ return "error","error"
+ print("res",res)
+ res = json.loads(res.text)
+ print("res",res)
+ #获取到model_size
+ modelSize = res['data']['model_size']
+ pid = res['data']['pid']
+ return pid,modelSize
+
+ except Exception as e:
+ print(f"获取订单信息异常: {str(e)}")
+ return "error","error"
+
+if __name__ == '__main__':
+ r = redis.Redis(host="106.14.158.208",password="kcV2000",port=6379,db=6)
+ while True:
+ print(f"时间-{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}")
+ if r.llen('model:weight') == 0:
+ print('队列为空,等待10秒')
+ time.sleep(10)
+ continue
+
+ # info 的数据格式为有以下几种情况 1. orderId 2 orderId_print_9,1.2,45,27 3. orderId_auto_9,1.2,45,27
+ info = r.lpop('model:weight')
+ if info is None:
+ print('队列为空,等待10秒')
+ time.sleep(10)
+ info = info.decode('utf-8')
+ orderId = 0
+ pid = 0
+ modelSize = []
+ typeModel = "print"
+ #判断info是什么类型的数据
+ arrInfo = info.split("_")
+ if len(arrInfo) == 1:
+ orderId = arrInfo[0]
+ pid,modelSize = getOrderInfoByOrderId(orderId)
+ if pid == "error":
+ print("获取订单信息失败")
+ continue
+
+ elif len(arrInfo) == 3:
+ orderId = arrInfo[0]
+ pid,temp = getOrderInfoByOrderId(orderId)
+ if pid == "error":
+ print("获取订单信息失败")
+ continue
+ typeModel = arrInfo[1]
+ modelSize = arrInfo[2]
+ if typeModel != "print" and typeModel != "auto":
+ print("typeModel类型不对")
+ continue
+
+
+ if int(orderId) == 0 or int(pid) == 0 or len(modelSize) == 0:
+ print("orderId pid modelSize 有出现问题")
+ continue
+
+ #转成数组
+ arrModelSize = modelSize.split(",")
+ print(f'执行脚本--- "python D:/make2/tools/cal_weight.py {typeModel} {pid} {modelSize} {orderId}"')
+ #发起计算请求
+ os.system(f"python D:/make2/tools/cal_weight.py {typeModel} {pid} {modelSize} {orderId}")
diff --git a/timer/init_timer.py b/timer/init_timer.py
new file mode 100644
index 0000000..d23cc92
--- /dev/null
+++ b/timer/init_timer.py
@@ -0,0 +1,8 @@
+import time,os
+if __name__ == '__main__':
+ #开启死循环
+ while True:
+ #检测当前打印 和 脚底板 和 gs 队列长度
+ os.system("python E:\\make2\\tools\\push_cmd.py auto_view")
+ #一个小时检测一次
+ time.sleep(60*60)
\ No newline at end of file
diff --git a/timer/setup_oem_exe.py b/timer/setup_oem_exe.py
index 2d2b631..0221897 100644
--- a/timer/setup_oem_exe.py
+++ b/timer/setup_oem_exe.py
@@ -3,7 +3,7 @@ import redis,requests,json,os,sys
import platform
if platform.system() == 'Windows':
- sys.path.append('e:\\libs\\')
+ sys.path.append('e:\\make2\\libs\\')
else:
sys.path.append('/data/deploy/make3d/make2/libs/')
import config
@@ -66,32 +66,32 @@ def main():
print(data['data'])
#pythob 进入到 E:\wails\oemProject ,将 data 数据写入到 wails.json 文件中的 ext_oem 字段中
- with open("D:\\oemProject\\wails.json","r",encoding="utf-8") as f:
+ with open("E:\\make2\\oemProject\\wails.json","r",encoding="utf-8") as f:
wailsData = json.load(f)
wailsData['ext_oem'] = data['data']
wailsData['name'] = data['data']['brand_name']
wailsData["outputfilename"] = str(data['data']['id'])
- with open("D:\\oemProject\\wails.json","w",encoding="utf-8") as f:
+ with open("E:\\make2\\oemProject\\wails.json","w",encoding="utf-8") as f:
json.dump(wailsData,f,ensure_ascii=False,indent=4)
# #将图片下载到本地
- getExeImg(data['data']['logo'], "D:\\oemProject\\build\\appicon.png")
+ getExeImg(data['data']['exe_logo'], "E:\\make2\\oemProject\\build\\appicon.png")
#删除 D:\\oemProject\\build\\bin 目录下的所有exe 文件,不包含子目录
- delete_exe_files_in_dir("D:\\oemProject\\build\\bin")
+ delete_exe_files_in_dir("E:\\make2\\oemProject\\build\\bin")
# #重命名文件
# os.system(f"cd D:\\oemProject && ren build\\bin\\{data['data']['brand_name']}amd64-installer.exe "+str(data['data']['id'])+".exe")
#写入成功后在 E:\\wails\\oemProject\\ 目录下执行 wails build 命令 -debug
- os.system("cd D:\\oemProject && wails build -nsis")
+ os.system("cd E:\\make2\\oemProject && wails build -nsis -devtools")
time.sleep(35)
#删除指定目录下的多余产生的文件
- os.system("cd D:\\oemProject && del /s/q/f build\\bin\\"+str(data['data']['id'])+".exe")
+ os.system("cd E:\\make2\\oemProject && del /s/q/f build\\bin\\"+str(data['data']['id'])+".exe")
#打包压缩指定文件夹
# 指定要打包的文件夹路径
- folder_to_zip = 'D:\\oemProject\\build\\bin'
+ folder_to_zip = 'E:\\make2\\oemProject\\build\\bin'
# 指定生成的压缩包名称和路径
zip_filename = f"{str(data['data']['id'])}.zip"
@@ -104,7 +104,7 @@ def main():
#上传成功后,调用接口,告诉mp,已经生成exe及上传成功
requests.get(url+"/api/oem/infoSetupUpdate",params={"id":oemId})
#
- os.system("cd D:\\make2 && del /s/q/f timer\\"+str(data['data']['id'])+".zip")
+ os.system("cd E:\\make2 && del /s/q/f timer\\"+str(data['data']['id'])+".zip")
def getExeImg(image_url, output_path):
@@ -118,10 +118,10 @@ def getExeImg(image_url, output_path):
# 保存图片为PNG格式
resized_image.save(output_path, 'PNG')
#转换格式
- transToIco(output_path,"D:\\oemProject\\build\\windows\\icon.ico")
+ transToIco(output_path,"E:\\make2\\oemProject\\build\\windows\\icon.ico")
#复制图片到指定目录
time.sleep(3)
- shutil.copy("D:\\oemProject\\build\\windows\\icon.ico","D:\\oemProject\\build\\bin\\icon.ico",)
+ shutil.copy("E:\\make2\\oemProject\\build\\windows\\icon.ico","E:\\make2\\oemProject\\build\\bin\\icon.ico",)
else:
print(f"Failed to download image. Status code: {response.status_code}")
diff --git a/tools/base_data_fix.py b/tools/base_data_fix.py
new file mode 100644
index 0000000..fae4a09
--- /dev/null
+++ b/tools/base_data_fix.py
@@ -0,0 +1,102 @@
+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, probreg
+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_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.')
+ sys.exit(1)
+
+ 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', '_baseFixed.obj')
+ bpy.ops.wm.obj_export(filepath=output_file)
+ return obj
+
+
+def readTask():
+ # #读取数据库的任务
+ # pid = libs_db_temp.get_task_by_level()
+ # pid = str(pid)
+ # #下载pid的对应的oss端的文件
+ # tempName = libs.down_obj_from_oss_for_fix("E://obj_fix", pid, "print")
+ # if tempName == "":
+ # print("找不到对应的obj文件")
+ # #记录状态为异常 -1
+ # libs_db_temp.update_fix_status(pid,-1)
+ # return ""
+
+ # #记录状态为处理中
+ # libs_db_temp.update_fix_status(pid,1)
+ # #处理逻辑
+ # return pid
+ pid=7013
+
+ base_fix(f'E://obj_fix/{pid}/{pid}.obj')
+
+ # print(pid)
+ # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+"-读取数据库任务")
+
+#程序主入口
+if __name__ == '__main__':
+ #atexit.register(common.notify,"处理数据校准任务已经停止")
+ readTask()
+ # while True:
+ # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+"-开始执行任务")
+ # pid = readTask()
+ # if pid != "":
+ # break
\ No newline at end of file
diff --git a/tools/cal_weight.py b/tools/cal_weight.py
index 7ac9f76..0194643 100644
--- a/tools/cal_weight.py
+++ b/tools/cal_weight.py
@@ -1,4 +1,4 @@
-import os, sys, time, bpy, bmesh, shutil
+import os, sys, time, bpy, bmesh, shutil,requests,json
import platform
if platform.system() == 'Windows':
sys.path.append('e:\\libs\\')
@@ -64,16 +64,35 @@ def cal_weight(obj, size):
model_info['volume'] = round(bm.calc_volume() / 1000)
model_info['weight'] = round(model_info['volume'] * 1.226)
print(f'{size/10}cm:体积 {model_info["volume"]}cm³, 克重 {model_info["weight"]}g')
+ return model_info["weight"]
-def main(action, pid, sizes):
+def main(action, pid, sizes,orderId=0):
libs.down_obj_from_oss(config.workdir, pid, action)
obj = reload_obj(pid, action)
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
print(f'模型{pid}的体积与克重估算信息:')
+ arrData = {}
for size in sizes:
size = float(size)
- cal_weight(obj, size)
+ weight = cal_weight(obj, size)
+ size = str(size/10)+"cm"
+ arrData[size] = str(weight)+"g"
+
+ #请求接口进行更新数据
+ arrParams = {"pid":pid,"order_id":orderId}
+ if action == "auto":
+ arrParams["auto_weight"] = json.dumps(arrData)
+
+ if action == "print":
+ arrParams["print_weight"] = json.dumps(arrData)
+
+ #发起请求
+ print(f"请求的参数-{arrParams}")
+ url = "https://mp.api.suwa3d.com/api/physical/addPhysicalWeight"
+ res = requests.post(url,data=arrParams)
+ print('res:', res.text)
+
if __name__ == '__main__':
sizes = (90, 120, 150, 180)
@@ -83,10 +102,19 @@ if __name__ == '__main__':
pids = sys.argv[2].split(',')
for pid in pids:
main(action, pid, sizes)
+ elif len(sys.argv) == 5:
+ action = sys.argv[1]
+ pids = sys.argv[2].split(',')
+ sizes = sys.argv[3].split(',')
+ orderId = sys.argv[4]
+ for pid in pids:
+ main(action, pid, sizes,orderId)
+ print('Usage: python cal_weight.py print order_id 自定义尺寸/默认四个尺寸就不填')
+
elif len(sys.argv) == 4:
action = sys.argv[1]
pids = sys.argv[2].split(',')
sizes = sys.argv[3].split(',')
for pid in pids:
main(action, pid, sizes)
- print('Usage: python cal_weight.py print 自定义尺寸/默认四个尺寸就不填')
\ No newline at end of file
+ print('Usage: python cal_weight.py print order_id 自定义尺寸/默认四个尺寸就不填')
\ No newline at end of file
diff --git a/tools/get_weight_by_pid.py b/tools/get_weight_by_pid.py
new file mode 100644
index 0000000..002fb97
--- /dev/null
+++ b/tools/get_weight_by_pid.py
@@ -0,0 +1,43 @@
+import os,sys,requests,json
+
+
+if __name__ == "__main__":
+ #获取参数
+ args = sys.argv
+ print("args:",args)
+ if len(args) != 2:
+ print("参数错误")
+ exit()
+
+ pid = args[1]
+ print("pid",pid)
+ #根据pid查询order_id的集合
+ url="https://mp.api.suwa3d.com/api/physical/listOrderIdByPid?pid="+str(pid)
+ res=requests.get(url)
+ if res.status_code != 200:
+ print('获取失败,程序退出')
+ exit()
+ res = json.loads(res.text)
+ print("res",res)
+ if res["code"] != 1000:
+ exit()
+ orderIds = res['data']
+ print("orderIds:",orderIds)
+ #循环处理
+ for orderId in orderIds:
+ #os.system(f"python D:/make2/tools/cal_weight.py print {pid} {orderId}")
+ url = "https://mp.api.suwa3d.com/api/physical/infoModelSizeByOrderId?order_id="+str(orderId)
+ print("url:",url)
+ res = requests.get(url)
+ if res.status_code != 200:
+ print('获取失败,程序退出')
+ continue
+ print("res",res)
+ res = json.loads(res.text)
+ print("res",res)
+ #获取到model_size
+ modelSize = res['data']['model_size']
+ pid = res['data']['pid']
+ print(f"执行脚本 python D:/make2/tools/cal_weight.py auto {pid} {modelSize} {orderId}")
+ os.system(f"python D:/make2/tools/cal_weight.py auto {pid} {modelSize} {orderId}")
+ # python D:/make2/tools/get_weight_by_pid.py
\ No newline at end of file
diff --git a/tools/optimize_model/README.txt b/tools/optimize_model/README.txt
new file mode 100644
index 0000000..69e4ccd
--- /dev/null
+++ b/tools/optimize_model/README.txt
@@ -0,0 +1,6 @@
+1. pip install -r requirements.txt安装requirements.txt所需的python包 (python3.10)
+2. 使用python optimize_model.py -ip 输入的obj路径 -op 输出的obj路径
+
+
+
+python optimize_model.py -ip "D:\finished\190104\output\190104.obj" -op "D:\finished\190104\output\190104_new.obj"
\ No newline at end of file
diff --git a/tools/optimize_model/libs.py b/tools/optimize_model/libs.py
new file mode 100644
index 0000000..d8950b1
--- /dev/null
+++ b/tools/optimize_model/libs.py
@@ -0,0 +1,381 @@
+import os, time, json, requests, shutil, oss2, psutil
+from tqdm import tqdm
+from PIL import Image, ImageEnhance
+import config,libs_db,common
+import threading
+from concurrent.futures import ThreadPoolExecutor
+
+def find_blender_bin_path():
+ base_path = 'C:\\Program Files\\Blender Foundation\\'
+ if os.path.exists(base_path):
+ for dir in os.listdir(base_path):
+ if dir.startswith('Blender'):
+ blender_bin_path = base_path + dir + '\\blender.exe'
+ return f'"{blender_bin_path}"'
+ else:
+ print('未找到blender安装目录')
+ exit(1)
+
+def resize_photos(photo_path, ratio=0.5):
+ for filename in os.listdir(photo_path):
+ if filename.endswith('.jpg'):
+ img = Image.open(os.path.join(photo_path, filename))
+ img = rotate_image(img)
+ w, h = img.size
+ img = img.resize((int(w * ratio), int(h * ratio)))
+ img.save(os.path.join(photo_path, filename))
+
+def rotate_image(image):
+ # 检查图像的EXIF数据是否包含方向信息
+ try:
+ exif = image._getexif()
+ orientation = exif.get(0x0112)
+ except:
+ orientation = None
+
+ # 根据方向信息旋转图像
+ if orientation == 3:
+ image = image.rotate(180, expand=True)
+ elif orientation == 6:
+ image = image.rotate(270, expand=True)
+ elif orientation == 8:
+ image = image.rotate(90, expand=True)
+ return image
+
+def get_ps_adjust_photo_para(psid):
+ res = requests.get(config.urls['get_ps_adjust_photo_para_url'], params={'id': psid})
+ print(res.json())
+ paras = res.json()['data']
+ brightness_factor, saturation_factor, temperature_factor = float(paras['brightness']), float(paras['saturation']), float(paras['colorTemperature'])
+ return brightness_factor, saturation_factor, temperature_factor
+
+def adjust_photos(workdir, pid):
+ def adjust_brightness(image, brightness_factor):
+ if brightness_factor == 1 or brightness_factor == 0 :
+ return image
+ enhancer = ImageEnhance.Brightness(image)
+ adjusted_image = enhancer.enhance(brightness_factor)
+ return adjusted_image
+
+ def adjust_saturation(image, saturation_factor):
+ if saturation_factor == 1:
+ return image
+ enhancer = ImageEnhance.Color(image)
+ adjusted_image = enhancer.enhance(saturation_factor)
+ return adjusted_image
+
+ def adjust_temperature(image, temperature_factor):
+ if temperature_factor == 1:
+ return image
+ r, g, b = image.split()
+ r = r.point(lambda i: i * temperature_factor)
+ adjusted_image = Image.merge("RGB", (r, g, b))
+ return adjusted_image
+ if not os.path.exists(os.path.join(workdir, pid, 'photo2')):
+ print(f"Directory {os.path.join(workdir, pid, 'photo2')} does not exist")
+ return False
+
+ psid = getPSid(pid)
+ brightness_factor, saturation_factor, temperature_factor = get_ps_adjust_photo_para(psid)
+
+ if (brightness_factor == 1 and saturation_factor == 1 and temperature_factor == 1):
+ print("No need to adjust")
+ return False
+ if os.path.exists(os.path.join(workdir, pid, 'photo3')):
+ print(f'{os.path.join(workdir, pid, "photo3")}目录已存在,跳过')
+ return
+ os.makedirs(os.path.join(workdir, pid, 'photo3'), exist_ok=True)
+
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 开始调整图片曝光...')
+ start_time = time.time()
+ for filename in os.listdir(os.path.join(workdir, pid, 'photo2')):
+ if filename.endswith(".jpg"):
+ # print(f"Adjusting {filename}:brightness={brightness_factor}, saturation={saturation_factor}, temperature={temperature_factor}")
+ image = Image.open(os.path.join(workdir, pid, 'photo2', filename))
+ image = rotate_image(image)
+
+ brightened_image = adjust_brightness(image, brightness_factor)
+ saturated_image = adjust_saturation(brightened_image, saturation_factor)
+ adjusted_image = adjust_temperature(saturated_image, temperature_factor)
+
+ adjusted_image.save(os.path.join(workdir, pid, 'photo3', filename))
+ print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 图片曝光调整完成,共费时{diff_time(start_time)}')
+ return True
+
+def getPSid(pid):
+ res = requests.get(config.urls['get_psid_url'], params={'pid': pid})
+ print('get_psid_url:', res.url)
+ print('res:', res.text)
+ res = json.loads(res.text)
+ return str(res['data'])
+
+def getHeadCount(pid):
+ res = requests.get(config.urls['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_ps_type(pid):
+ # return 1:圆形影棚 2:方形影棚
+ res = requests.get(config.urls['get_ps_type_url'], params={'pid': pid})
+ return res.json()['data']['type']
+
+def find_valid_camera_on_oss(pid):
+ if get_ps_type(pid) == 1:
+ print('当前拍照影棚为:圆形影棚')
+ cameras = (103, 93, 113)
+ else:
+ print('当前拍照影棚为:方形影棚')
+ cameras = (74, 64, 84)
+ find_camera = 0
+ for camera in cameras:
+ objectkey = f'photos/{pid}/photo2/{camera}_8.jpg'
+ find = config.oss_bucket.object_exists(objectkey)
+ if find:
+ find_camera = camera
+ break
+
+ print('找到有效正脸相机:', find_camera)
+ if find_camera == 0:
+ print('{cameras}没有找到照片,程序退出')
+ exit(1)
+ return find_camera
+
+def aliyun_face(pid):
+ high = False
+ style = 'imm/detectface'
+ camera = find_valid_camera_on_oss(pid)
+ objectkey = f'photos/{pid}/photo2/{camera}_8.jpg'
+ try:
+ res = config.oss_bucket.get_object(objectkey, process=style)
+ except oss2.exceptions.NoSuchKey:
+ print('没有找到文件:', objectkey)
+ return high
+ res = json.loads(res.read())
+ if res['success']:
+ if res['Faces'] is None:
+ print('no face')
+ return None
+ else:
+ print('faces num:', len(res['Faces']))
+ for face in res['Faces']:
+ print('-' * 20)
+ print('face_id:', face['FaceId'])
+ print('gender:', face['Gender'])
+ print('age:', face['Age'])
+
+ if face['Gender'] == 'FEMALE' and face['Age'] < 22: high = True
+ if face['Gender'] == 'MALE' and face['Age'] < 15: high = True
+ else:
+ print('face detect failed...')
+ return high
+
+def down_obj_from_oss(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('.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
+
+def set_photos_join_type(workdir, pid, photoN, mesh = '0', texture='0'):
+ photoN_path = os.path.join(workdir, pid, photoN)
+ for xmp in os.listdir(photoN_path):
+ if xmp.endswith('.xmp'):
+ xmp_path = os.path.join(photoN_path, xmp)
+ with open(xmp_path, 'r') as f:
+ lines = f.readlines()
+ lines = [line.replace('xcr:InMeshing="0"', f'xcr:InMeshing="{mesh}"') for line in lines]
+ lines = [line.replace('xcr:InMeshing="1"', f'xcr:InMeshing="{mesh}"') for line in lines]
+ lines = [line.replace('xcr:InTexturing="0"', f'xcr:InTexturing="{texture}"') for line in lines]
+ lines = [line.replace('xcr:InTexturing="1"', f'xcr:InTexturing="{texture}"') for line in lines]
+ with open(xmp_path, 'w') as f:
+ f.writelines(lines)
+
+def set_photo_join_type(workdir, pid, photoN, camera_id, mesh = '0', texture='0'):
+ if photoN == 'photo1':
+ filename = os.path.join(workdir, pid, photoN, f'{camera_id}_1.xmp')
+ else:
+ filename = os.path.join(workdir, pid, photoN, f'{camera_id}_8.xmp')
+ with open(filename, 'r') as f:
+ lines = f.readlines()
+ lines = [line.replace('xcr:InMeshing="0"', f'xcr:InMeshing="{mesh}"') for line in lines]
+ lines = [line.replace('xcr:InMeshing="1"', f'xcr:InMeshing="{mesh}"') for line in lines]
+ lines = [line.replace('xcr:InTexturing="0"', f'xcr:InTexturing="{texture}"') for line in lines]
+ lines = [line.replace('xcr:InTexturing="1"', f'xcr:InTexturing="{texture}"') for line in lines]
+ with open(filename, 'w') as f:
+ f.writelines(lines)
+
+def down_from_oss(oss_client, workdir, pid, per=100,photoPath=""):
+ start_time = time.time()
+ path = os.path.join(workdir, pid)
+ if os.path.exists(path):
+ print(f"Directory {path} already exists, skip")
+ return
+ os.makedirs(os.path.join(path, 'photo1'))
+ os.makedirs(os.path.join(path, 'photo2'))
+
+ psid = getPSid(pid)
+ # 根据前缀获取文件列表
+ prefix = f'photos/{pid}/'
+ filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix)
+ for file in tqdm(filelist):
+ filename = file.key.split('/')[-1]
+ localfile = ""
+ # print('正在下载:', file.key)
+ if photoPath == "":
+ if filename.endswith('_1.jpg'):
+ localfile = os.path.join(path, 'photo1', filename)
+ else:
+ localfile = os.path.join(path, 'photo2', filename)
+ else:
+ 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}'
+ if per == 100:
+ oss_client.get_object_to_file(file.key, localfile)
+ else:
+ 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)}')
+
+#灰度处理图片
+def process_image(localfile):
+ if ".jpg" in localfile:
+ common.remove_gray_and_sharpening(localfile)
+
+def get_defineDistances(psid):
+ res = ''
+ distances = libs_db.get_floor_sticker_distances(psid).split(';')
+ print("distances",distances)
+ for d in distances:
+ p1, p2, distance = d.split(' ')
+ res = res + f' -defineDistance {p1} {p2} {distance}'
+ return res.strip()
+
+def is_running(psname):
+ for p in psutil.process_iter(['name']):
+ if psname.strip() in p.info['name']:
+ return True
+ return False
+
+def diff_time(start_time):
+ # 按照分:秒的方式返回时间差
+ end_time = time.time()
+ diff = end_time - start_time
+ m, s = divmod(diff, 60)
+ 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
+
+def down_obj_from_oss_for_repeat_texture(workdir, pid, action):
+ print(os.path.join(workdir, pid))
+ if not os.path.exists(os.path.join(workdir, pid)):
+ print("目录不存在,无法处理")
+ return "error"
+
+ #判断是否有专门新建的目录用来重新贴图
+ newPath = os.path.join(workdir, pid,'repeat_texture','completion_cloud')
+ if not os.path.exists(newPath):
+ os.makedirs(newPath)
+
+
+ # 根据前缀获取文件列表
+ prefix = f'objs/{action}/{pid}/ai/repeat_texture/completion_cloud'
+ filelist = oss2.ObjectIteratorV2(config.oss_bucket, prefix=prefix)
+ print('正在下载:', prefix)
+ for file in filelist:
+ filename = file.key.split('/')[-1]
+ if filename == "":
+ continue
+ localfile = os.path.join(newPath, filename)
+ config.oss_bucket.get_object_to_file(file.key, localfile)
+ return newPath
+
+
+
+
+def down_obj_from_oss_auto(pid,action,pathStr):
+ #pathStr = os.path.join(workdir, str(pid)+"_ai")
+ if not os.path.exists(pathStr):
+ os.makedirs(pathStr)
+
+ # 根据前缀获取文件列表
+ prefix = f'objs/{action}/{pid}'
+ filelist = oss2.ObjectIteratorV2(config.oss_bucket, prefix=prefix)
+ print('正在下载:', prefix)
+ for file in filelist:
+ filename = file.key.split('/')[-1]
+ if filename == "":
+ continue
+
+ if filename != f"{pid}.jpg" and filename != f"{pid}.obj" and filename != f"{pid}.mtl":
+ continue
+
+ print(filename)
+ localfile = os.path.join(pathStr, filename)
+ config.oss_bucket.get_object_to_file(file.key, localfile)
\ No newline at end of file
diff --git a/tools/optimize_model/main.py b/tools/optimize_model/main.py
new file mode 100644
index 0000000..6313a68
--- /dev/null
+++ b/tools/optimize_model/main.py
@@ -0,0 +1,31 @@
+import paramiko,time,sys
+
+def main_optimize_model(pid):
+ try:
+ # 创建SSH对象
+ ssh = paramiko.SSHClient()
+ # 允许连接不在known_hosts文件中的主机
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ print('start connect')
+ # 连接服务器
+ ssh.connect('connect.bjc1.seetacloud.com', username='root', password='QoQA8q3Ds2VB', port=33733)
+ print('connect success')
+
+ # 使用nohup执行命令,并将输出重定向到文件
+ command = f'nohup seg_python /data/code/optimize_model_xj/optimize_model.py -pid {pid} >{pid}.log 2>&1&'
+ stdin, stdout, stderr = ssh.exec_command(command)
+
+ # 打印命令是否启动成功
+ print("Command executed")
+ finally:
+ # 确保连接被关闭
+ if ssh:
+ time.sleep(1)
+ ssh.close()
+
+if __name__ == '__main__':
+
+ if len(sys.argv) == 2:
+ pid = sys.argv[1]
+ main_optimize_model(pid)
+
diff --git a/tools/optimize_model/optimize_model.py b/tools/optimize_model/optimize_model.py
new file mode 100644
index 0000000..e7dd005
--- /dev/null
+++ b/tools/optimize_model/optimize_model.py
@@ -0,0 +1,244 @@
+import bpy
+import sys
+import open3d as o3d
+import numpy as np
+from sklearn.neighbors import NearestNeighbors
+import os
+import argparse
+
+def estimate_point_curvatures(point_cloud, k=30):
+ point_cloud_points = np.asarray(point_cloud.points)
+ # Initialize the nearest neighbors finder
+ nn = NearestNeighbors(n_neighbors=k)
+ nn.fit(point_cloud_points)
+ curvatures = {i: 0 for i in range(len(point_cloud.points))}
+ for i, point in enumerate(point_cloud_points):
+ # Find the k-nearest neighbors (including the point itself)
+ distances, indices = nn.kneighbors([point])
+ neighbors = point_cloud_points[indices[0]]
+ # Compute the covariance matrix
+ covariance_matrix = np.cov(neighbors - neighbors.mean(axis=0), rowvar=False)
+ # Compute the eigenvalues (sorted)
+ eigenvalues, _ = np.linalg.eigh(covariance_matrix)
+ eigenvalues.sort()
+ # Calculate curvature using the smallest eigenvalue
+ curvature = eigenvalues[0] / sum(eigenvalues)
+ curvatures[i] = curvature
+ return curvatures
+
+def compute_adjacent_normal_angle_variance(pcd, pcd_normal, distance_scale):
+ kdtree = o3d.geometry.KDTreeFlann(pcd)
+ distances = []
+ for i in range(len(pcd.points)):
+ [k, idx, dist] = kdtree.search_knn_vector_3d(pcd.points[i], 2)
+ dist = dist[1:] # distances to the actual neighbors
+ distances.append(dist)
+ mean_distance = np.mean(distances)
+ adjacent_normal_angles_variance = {i: 0 for i in range(len(np.asarray(pcd.points)))}
+ for i, point in enumerate(pcd.points):
+ # Search for the k-nearest neighbors of the point, up to 1500
+ k, idx, dist = kdtree.search_knn_vector_3d(point, 200)
+ idx = np.asarray(idx)
+ indices = idx[dist < mean_distance * distance_scale]
+ current_normal = pcd_normal[i]
+ # Calculate dot products between the current normal and its neighbors' normals
+ dot_products = np.dot(pcd_normal[indices], current_normal)
+ # Handle any potential NaN values in dot products
+ valid_dot_products = np.isfinite(dot_products)
+ dot_products = dot_products[valid_dot_products]
+ # Clip dot product values to valid range for arccos
+ dot_products = np.clip(dot_products, -1.0, 1.0)
+ # Compute angles in degrees and adjust for any NaNs which might be due to numerical errors
+ angles_array = np.degrees(np.arccos(dot_products))
+ # Set the angle with itself to zero since it's not meaningful
+ angles_array[indices == i] = 0
+ # Calculate the mean angle excluding the zero for the current point
+ valid_angles = angles_array[indices != i]
+ if valid_angles.size > 0:
+ adjacent_normal_angles_variance[i] = np.std(valid_angles)
+ else:
+ adjacent_normal_angles_variance[i] = 0 # Default to 0 if no valid neighbors exist
+ return adjacent_normal_angles_variance
+
+def compute_adjacent_point_vector_degrees_mean(pcd, pcd_normal, distance_scale):
+ kdtree = o3d.geometry.KDTreeFlann(pcd)
+ distances = []
+ for i in range(len(pcd.points)):
+ [k, idx, dist] = kdtree.search_knn_vector_3d(pcd.points[i], 2)
+ dist = dist[1:] # distances to the actual neighbors
+ distances.append(dist)
+ mean_distance = np.mean(distances)
+ adjacent_point_vector_degrees_mean = {i: 0 for i in range(len(np.asarray(pcd.points)))}
+ for i, point in enumerate(pcd.points):
+ # Search for the k-nearest neighbors of the point, up to 200
+ k, idx, dist = kdtree.search_knn_vector_3d(point, 200)
+ idx = np.asarray(idx)
+ indices = idx[dist < mean_distance * distance_scale]
+ indices = indices[indices != i]
+ # Retrieve the normal of the current point
+ current_normal = pcd_normal[i]
+ adjacent_point_vector = np.asarray(pcd.points)[indices] - point
+ adjacent_point_vector_cos = np.dot(adjacent_point_vector, current_normal) / np.linalg.norm(adjacent_point_vector, axis = 1) * 1
+ valid_adjacent_point_vector_cos = np.isfinite(adjacent_point_vector_cos)
+ adjacent_point_vector_cos = adjacent_point_vector_cos[valid_adjacent_point_vector_cos]
+ if len(adjacent_point_vector_cos) > 0:
+ adjacent_point_vector_degrees = np.degrees(np.arccos(adjacent_point_vector_cos))
+ adjacent_point_vector_mean_degrees = np.mean(adjacent_point_vector_degrees)
+ adjacent_point_vector_degrees_mean[i] = adjacent_point_vector_mean_degrees
+ else:
+ adjacent_point_vector_degrees_mean[i] = 0
+ return adjacent_point_vector_degrees_mean
+
+def spread_point(pcd, selected_index, distance_scale, count = False):
+ kdtree = o3d.geometry.KDTreeFlann(pcd)
+ distances = []
+ for i in range(len(pcd.points)):
+ [k, idx, dist] = kdtree.search_knn_vector_3d(pcd.points[i], 2)
+ dist = dist[1:] # distances to the actual neighbors
+ distances.append(dist)
+ mean_distance = np.mean(distances)
+ if count is False:
+ spread_selected_index = set()
+ for i in selected_index:
+ k, idx, dist = kdtree.search_knn_vector_3d(pcd.points[i], 200)
+ idx = np.asarray(idx)
+ dist = np.asarray(dist)
+ indices = idx[dist < mean_distance * distance_scale]
+ spread_selected_index.update(indices)
+ spread_selected_index = np.array(list(spread_selected_index))
+ else:
+ spread_selected_index = {i: 0 for i in range(len(np.asarray(pcd.points)))}
+ for i in selected_index:
+ k, idx, dist = kdtree.search_knn_vector_3d(pcd.points[i], 200)
+ idx = np.asarray(idx)
+ dist = np.asarray(dist)
+ indices = idx[dist < mean_distance * distance_scale]
+ for indice in indices:
+ spread_selected_index[indice] += 1
+ return spread_selected_index
+
+def ApplySmoothEffort(object, selected_vertice_indices = None, factor = 0.5, iterations = 30):
+ if selected_vertice_indices is not None:
+ # Assuming 'mesh' is already defined, e.g., mesh = bpy.context.object.data
+ selected_vertices_index = set() # Initialize an empty set to store unique vertex indices
+ # Iterate over each index in the list of polygon indices
+ for idx in selected_vertice_indices:
+ polygon = object.data.polygons[idx]
+ for vert_idx in polygon.vertices:
+ selected_vertices_index.add(vert_idx)
+ # Switch to Edit mode
+ bpy.ops.object.mode_set(mode='EDIT')
+ # Ensure we're dealing with the latest data
+ bpy.ops.object.mode_set(mode='OBJECT')
+ for i, vertex in enumerate(object.data.vertices):
+ vertex.select = False
+ if i in selected_vertices_index:
+ vertex.select = True
+ # Update the object to reflect changes
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.object.mode_set(mode='OBJECT')
+ # Add a Smooth modifier and set it to use the vertex group
+ smooth_mod = object.modifiers.new(name="SmoothMod", type='SMOOTH')
+ if selected_vertice_indices is not None:
+ # Create a new vertex group
+ group = object.vertex_groups.new(name='Smooth Group')
+ # Add selected vertices to the vertex group
+ group.add([v.index for v in object.data.vertices if v.select], weight=1.0, type='ADD')
+ smooth_mod.vertex_group = 'Smooth Group'
+ smooth_mod.factor = factor
+ smooth_mod.iterations = iterations
+ # bpy.ops.object.modifier_apply(modifier="SmoothMod")
+ # if selected_vertice_indices is not None:
+ # object.vertex_groups.clear()
+
+def process(input_mesh_path, output_mesh_path):
+ # Select and delete all objects in the current scene to start fresh
+ bpy.ops.object.select_all(action='SELECT')
+ bpy.ops.object.delete(confirm=False)
+ # Path to the OBJ file to be imported
+ bpy.ops.wm.obj_import(filepath=input_mesh_path)
+ # Set the current object to the newly imported mesh
+ current_obj = bpy.context.object
+ # Retrieve the mesh data from the current object
+ mesh_data = current_obj.data
+ bpy.context.view_layer.update()
+ # Convert Blender mesh vertices to a NumPy array
+ vertices_array = np.array([vertex.co[:] for vertex in mesh_data.vertices])
+ # Convert Blender mesh polygons to a NumPy array of triangles
+ triangles_array = np.array([polygon.vertices[:] for polygon in mesh_data.polygons])
+
+ # Create an Open3D mesh object from the arrays
+ open3d_mesh = o3d.geometry.TriangleMesh()
+ open3d_mesh.vertices = o3d.utility.Vector3dVector(vertices_array)
+ open3d_mesh.triangles = o3d.utility.Vector3iVector(triangles_array)
+ open3d_mesh.compute_triangle_normals()
+ # Retrieve and store the normals as a NumPy array
+ triangle_normals_array = np.asarray(open3d_mesh.triangle_normals)
+
+ # Compute centroids for each face of the mesh
+ triangle_centroids_array = np.array([
+ np.mean(vertices_array[triangle], axis=0)
+ for triangle in open3d_mesh.triangles
+ ])
+ # Create a point cloud of face centroids
+ pcd_triangle_centroid = o3d.geometry.PointCloud()
+ pcd_triangle_centroid.points = o3d.utility.Vector3dVector(triangle_centroids_array)
+
+ point_curvatures = estimate_point_curvatures(pcd_triangle_centroid, 30)
+ np_point_curvatures = np.array(list(point_curvatures.values()))
+ point_curvatures_index = np.arange(len(np_point_curvatures))[np_point_curvatures > 0.25]
+
+ spread_point_curvatures_index = spread_point(pcd_triangle_centroid, point_curvatures_index, 50)
+
+ ApplySmoothEffort(current_obj, spread_point_curvatures_index, 0.5, 30)
+
+ adjacent_normal_angle_variance = compute_adjacent_normal_angle_variance(pcd_triangle_centroid, triangle_normals_array, 40)
+ adjacent_point_vector_degrees_mean = compute_adjacent_point_vector_degrees_mean(pcd_triangle_centroid, triangle_normals_array, 40)
+
+ array_adjacent_point_vector_degrees_mean = np.array(list(adjacent_point_vector_degrees_mean.values()))
+ array_adjacent_normal_angle_variance = np.array(list(adjacent_normal_angle_variance.values()))
+
+ use_data = np.where(array_adjacent_point_vector_degrees_mean < 90, array_adjacent_normal_angle_variance, 0)
+ # Calculate the minimum and maximum values in the angle array, ignoring NaNs.
+ min_angle = np.nanmin(use_data)
+ max_angle = np.nanmax(use_data)
+ # Perform min-max normalization on the angles to scale them between 0 and 1.
+ # This normalization helps in comparing values on a common scale.
+ normalized_angles = (use_data - min_angle) / (max_angle - min_angle)
+ first_select_thread = normalized_angles > 0.2
+ first_select_thread_number = first_select_thread.astype(np.float64)
+ thread_normalized_angles_index = np.arange(len(first_select_thread))[first_select_thread]
+
+ spread_point_count = spread_point(pcd_triangle_centroid, thread_normalized_angles_index, 3, count=True)
+
+ overlapp_trigular_points = np.array(list(spread_point_count.values())) > 3
+ overlapp_trigular_points_index = np.arange(len(overlapp_trigular_points))[overlapp_trigular_points]
+
+ ApplySmoothEffort(current_obj, overlapp_trigular_points_index, 0.5, 30)
+
+ ApplySmoothEffort(current_obj, factor=0.5, iterations=30)
+
+ bpy.ops.wm.obj_export(filepath=output_mesh_path)
+
+def process_meshes(input_path, output_path):
+ """
+ Processes each mesh file in the input directory and saves the cleaned meshes in the output directory.
+
+ Args:
+ input_path (str): Directory containing the input meshes or a single mesh file.
+ output_path (str): Directory where the cleaned meshes will be saved.
+ """
+ if os.path.isdir(input_path):
+ for filename in sorted(os.listdir(input_path)):
+ full_input_path = os.path.join(input_path, filename)
+ full_output_path = os.path.join(output_path, filename)
+ process(full_input_path, full_output_path)
+ else:
+ process(input_path, output_path)
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(description="Processes mesh files.")
+ parser.add_argument("-ip", "--input_path", type=str, required=True, help="Input path for the mesh file or directory.")
+ parser.add_argument("-op", "--output_path", type=str, required=True, help="Output path for the cleaned mesh file or directory.")
+ args = parser.parse_args()
+ process_meshes(args.input_path, args.output_path)
diff --git a/tools/optimize_model/requirements.txt b/tools/optimize_model/requirements.txt
new file mode 100644
index 0000000..ec8d4be
--- /dev/null
+++ b/tools/optimize_model/requirements.txt
@@ -0,0 +1,5 @@
+open3d
+numpy
+sklearn
+argparse
+bpy
diff --git a/tools/optimize_model/run.py b/tools/optimize_model/run.py
new file mode 100644
index 0000000..c0735a0
--- /dev/null
+++ b/tools/optimize_model/run.py
@@ -0,0 +1,78 @@
+
+import os,sys,time,shlex,subprocess,shutil,requests,json
+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 libs,config
+def main(pid = 0):
+ print(f'开始时间-{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}')
+ if pid == 0:
+ #获取要处理PID的url
+ url = "https://repair.api.suwa3d.com/api/modelRepairOrder/getRepairOrderListByPriority"
+ #发起请求
+ res = requests.get(url)
+ print('res:', res.text)
+ if res.status_code != 200:
+ print('获取失败,程序退出')
+ return
+ res = json.loads(res.text)
+ pid = 0
+ try:
+ pid = res['data']['pid']
+ except Exception as e:
+ return 0
+
+ if pid == 0:
+ return 0
+
+ #调用oss下载功能,下载对应的文件
+ pathStr = os.path.join(config.workdir,str(pid)+"_ai")
+ libs.down_obj_from_oss_auto(str(pid),"auto",pathStr)
+ #检查是否存在产生的对应的文件
+ if not os.path.exists(os.path.join(pathStr,f'{pid}.obj')):
+ print(f"找不到{pid}obj文件")
+ return
+
+ if not os.path.exists(os.path.join(pathStr,f'{pid}.mtl')):
+ print(f"找不到{pid}mtl文件")
+ return
+ #下载完成后调用
+ os.system(f"python optimize_model.py -ip {pathStr}/{pid}.obj -op {pathStr}/{pid}_ai.obj")
+ #检查是否存在产生的对应的文件
+ if not os.path.exists(os.path.join(pathStr,f'{pid}_ai.obj')):
+ print(f"找不到{pid}ai_obj文件")
+ return
+
+ if not os.path.exists(os.path.join(pathStr,f'{pid}_ai.mtl')):
+ print(f"找不到{pid}ai_mtl文件")
+ return
+
+ #处理完成完后上传到oss指定目录
+ config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/ai/fix_mesh/{pid}_ai.obj', os.path.join(pathStr,f'{pid}_ai.obj'))
+ config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/ai/fix_mesh/{pid}_ai.mtl', os.path.join(pathStr,f'{pid}_ai.mtl'))
+ config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/ai/fix_mesh/{pid}.jpg', os.path.join(pathStr,f'{pid}.jpg'))
+ #更新处理结果
+ url = "https://repair.api.suwa3d.com/api/modelRepairOrder/updateShootOrderBuildModelType?pid="+str(pid)
+ #发起请求
+ requests.get(url)
+ #移除文件夹
+ shutil.rmtree(pathStr)
+ print(f'结束时间-{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}')
+
+
+
+if __name__ == '__main__':
+
+ if len(sys.argv) == 2:
+ pid = sys.argv[1]
+ main(pid)
+ print(f"{pid}-处理结束")
+ else:
+ while True:
+ res = main()
+ if res == 0:
+ print("休眠60s")
+ time.sleep(60)
\ No newline at end of file
diff --git a/tools/optimize_model/test.py b/tools/optimize_model/test.py
new file mode 100644
index 0000000..3a87e08
--- /dev/null
+++ b/tools/optimize_model/test.py
@@ -0,0 +1,22 @@
+import paramiko
+
+try:
+ # 创建SSH对象
+ ssh = paramiko.SSHClient()
+ # 允许连接不在known_hosts文件中的主机
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ print('start connect')
+ # 连接服务器
+ ssh.connect('connect.bjc1.seetacloud.com', username='root', password='QoQA8q3Ds2VB', port=33733)
+ print('connect success')
+
+ # 使用nohup执行命令,并将输出重定向到文件
+ command = 'nohup seg_python /data/code/optimize_model_xj/optimize_model.py -pid 189813 > output.log 2>&1 &'
+ stdin, stdout, stderr = ssh.exec_command(command)
+
+ # 打印命令是否启动成功
+ print("Command executed")
+finally:
+ # 确保连接被关闭
+ if ssh:
+ ssh.close()
diff --git a/tools/push_cmd.py b/tools/push_cmd.py
index c8f9223..651901d 100644
--- a/tools/push_cmd.py
+++ b/tools/push_cmd.py
@@ -1,10 +1,10 @@
-import redis, os, sys,requests,platform
+import redis, os, sys,requests,platform,json
if platform.system() == 'Windows':
- sys.path.append('e:\\libs\\')
+ sys.path.append('E:\\make2\\libs\\')
#sys.path.append('libs')
else:
sys.path.append('/data/deploy/make3d/make2/libs/')
-import config, libs,libs_db
+import config, libs,libs_db,libs_db_task_rc
def main(cmd, order_id):
if cmd == 'print': #order_id
@@ -19,17 +19,45 @@ def main(cmd, order_id):
key = 'model:foot'
elif cmd == 'rebuild': #pid
key = 'model:rebuild'
+ elif cmd == 'gs':
+ key = 'ai:ai_build'
if order_id == 'view':
- for i in r.lrange(key, 0, -1):
- print(i)
- print(f'当前{key}队列长度:{r.llen(key)}')
+ if cmd == "rc_model_build":
+ nums = libs_db_task_rc.get_task_rc_count()
+ print(f'当前{cmd}队列长度:{nums}')
+ notify(f'当前{cmd}队列长度:{nums}')
+ else:
+ print(f'当前{cmd}队列长度:{r.llen(key)}')
+ notify(f'当前{cmd}队列长度:{r.llen(key)}')
+
+
+ for i in r.lrange(key, 0, -1):
+ print(i)
+ print(f'当前{key}队列长度:{r.llen(key)}')
else:
order_ids = order_id.split(',')
for order_id in order_ids:
r.lpush(key, order_id)
print(f'已推送{order_id}到{key}, 当前队列长度:{r.llen(key)}')
+
+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)
+
+
+
def cmd(cmdName,pid):
if pid == "view":
key = ""
@@ -43,10 +71,18 @@ def cmd(cmdName,pid):
key = 'model:make10'
elif cmdName == 'foot': # print_id
key = 'model:foot'
- for i in r.lrange(key, 0, -1):
- print(i)
- print(f'当前{key}队列长度:{r.llen(key)}')
- exit()
+
+ if pid == 'view':
+ # for i in r.lrange(key, 0, -1):
+ # print(i)
+ print(f'当前{cmd}队列长度:{r.llen(key)}')
+ notify(f'当前{cmd}队列长度:{r.llen(key)}')
+ exit()
+ else:
+ for i in r.lrange(key, 0, -1):
+ print(i)
+ print(f'当前{key}队列长度:{r.llen(key)}')
+ exit()
res = requests.get(f'https://mp.api.suwa3d.com/api/infoQuery/infoByPid?pid={pid}&cmd={cmdName}')
#获取res 的数据
@@ -135,13 +171,24 @@ def listDataToStr(data,cmdName):
if __name__ == '__main__':
+ r = config.redis_remote
if len(sys.argv) == 3:
cmdName = sys.argv[1]
pid = sys.argv[2]
+
+ elif len(sys.argv) == 2:
+ cmd = sys.argv[1]
+ order_id = 'view'
+ if cmd == "auto_view":
+ arrCmd = ["print","foot","gs","rc_model_build"]
+ for cmdV in arrCmd:
+ main(cmdV, order_id)
+
+ exit(1)
else:
print('用法:python push_cmd.py ')
exit(1)
- r = config.redis_remote
+
#pid 可能是多个的,用逗号分隔,查询的时候接口应该也要支持多个的
if cmdName == 'make3d' or cmdName == 'make3d10' or cmdName == 'rebuild':
diff --git a/建模碎片步骤.txt b/建模碎片步骤.txt
index dfeb31b..bfb847d 100644
--- a/建模碎片步骤.txt
+++ b/建模碎片步骤.txt
@@ -1,3 +1,42 @@
#建模完成,需要减面 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
\ No newline at end of file
+%bin% -delegateTo 161082 -simplify 2000000 -smooth -closeHoles -cleanModel -calculateTexture -save "D:\161082\161082.rcproj" -exportSelectedModel "D:\161082\output\161082.obj" "d:\make2\config\ModelExportParams.xml"
+
+
+
+%bin% -delegateTo 161082 -defineDistance 36h11:007 36h11:008 0.21 -update -align -align -setReconstructionRegionOnCPs 36h11:001 36h11:002 36h11:003 2.1 -moveReconstructionRegion 0 0 -2.1 -rotateReconstructionRegion 180 0 180 -setGroundPlaneFromReconstructionRegion -scaleReconstructionRegion 1.8 1.6 2.1 absolute center -moveReconstructionRegion 0 0 0.0025 -exportXMP "D:\make2\config\exportXMP.config.xml"
+
+
+%bin% -delegateTo 156600 -defineDistance 36h11:001 36h11:002 1 -update -setReconstructionRegionOnCPs 36h11:001 36h11:002 36h11:004 2.1 -moveReconstructionRegion 0 0 -2.1 -rotateReconstructionRegion 180 0 180 -setGroundPlaneFromReconstructionRegion -scaleReconstructionRegion 1.8 1.6 2.1 absolute center -moveReconstructionRegion 0 0 0.0025 -exportXMP "D:\make2\config\exportXMP.config.xml"
+
+
+%bin% -delegateTo 156600 -defineDistance 36h11:007 36h11:008 0.21 -update -align -align -setReconstructionRegionOnCPs 36h11:001 36h11:002 36h11:004 2.1 -moveReconstructionRegion 0 0 -2.1 -rotateReconstructionRegion 180 0 180 -setGroundPlaneFromReconstructionRegion -scaleReconstructionRegion 1.8 1.6 2.1 absolute center -moveReconstructionRegion 0 0 0.0025 -exportXMP "D:\make2\config\exportXMP.config.xml" -exportReconstructionRegion "D:\156600\156600.rcbox" -selectImage "D:\156600\photo2/*" -enableTexturingAndColoring true -save "D:\156600\156600.rcproj"
+
+%bin% -delegateTo 156600 -setReconstructionRegionOnCPs 36h11:001 36h11:002 36h11:003 2.1 -moveReconstructionRegion 0 0 -2.1 -rotateReconstructionRegion 180 0 180 -setGroundPlaneFromReconstructionRegion -scaleReconstructionRegion 1.8 1.6 2.1 absolute center -moveReconstructionRegion 0 0 0.0025 -exportXMP "D:\make2\config\exportXMP.config.xml" -exportControlPointsMeasurements "D:\156600\156600.controlPoints.csv" "D:\make2\config\exportControlPoints.config.xml" -exportReconstructionRegion "D:\156600\156600.rcbox" -selectImage "D:\156600\photo2\*" -enableTexturingAndColoring true -save "D:\156600\156600.rcproj"
+
+
+ -defineDistance 36h11:007 36h11:008 0.21 -update -align -align -setReconstructionRegionOnCPs 36h11:001 36h11:002 36h11:003 2.1 -moveReconstructionRegion 0 0 -2.1 -rotateReconstructionRegion 180 0 180 -setGroundPlaneFromReconstructionRegion -scaleReconstructionRegion 1.8 1.6 2.1 absolute center -moveReconstructionRegion 0 0 0.0025 -exportXMP "D:\make2\config\exportXMP.config.xml" -exportReconstructionRegion "D:\140241\140241.rcbox" -selectImage "D:\140241\photo2/*" -enableTexturingAndColoring true -save "D:\140241\140241.rcproj"
+
+-defineDistance 36h11:007 36h11:008 0.21 -align -align -update -setReconstructionRegionOnCPs 36h11:001 36h11:002 36h11:003 2.1 -moveReconstructionRegion 0 0 -2.1 -rotateReconstructionRegion 180 0 180 -setGroundPlaneFromReconstructionRegion -scaleReconstructionRegion 1.8 1.6 2.1 absolute center -moveReconstructionRegion 0 0 0.0025 -exportXMP "D:\make2\config\exportXMP.config.xml" -exportControlPointsMeasurements "D:\147024\147024.controlPoints.csv" "D:\make2\config\exportControlPoints.config.xml" -exportReconstructionRegion "D:\147024\147024.rcbox" -selectImage "D:\147024\photo2\*" -enableTexturingAndColoring true -save "D:\147024\147024.rcproj"
+
+
+%bin% -delegateTo 155007 -defineDistance 36h11:007 36h11:008 0.21 -update -align -align -setReconstructionRegionOnCPs 36h11:001 36h11:002 36h11:004 2.1 -moveReconstructionRegion 0 0 -2.1 -rotateReconstructionRegion 180 0 180 -setGroundPlaneFromReconstructionRegion -scaleReconstructionRegion 1.8 1.6 2.1 absolute center -moveReconstructionRegion 0 0 0.0025 -exportXMP "D:\make2\config\exportXMP.config.xml" -exportReconstructionRegion "D:\155007\155007.rcbox" -save "D:\155007\155007.rcproj"
+
+
+
+
+%bin% -delegateTo 153982 -defineDistance 36h11:007 36h11:008 0.21 -update -align -align -setReconstructionRegionOnCPs 36h11:001 36h11:002 36h11:004 2.1 -moveReconstructionRegion 0 0 -2.1 -rotateReconstructionRegion 180 0 180 -setGroundPlaneFromReconstructionRegion -scaleReconstructionRegion 1.8 1.6 2.1 absolute center -moveReconstructionRegion 0 0 0.0025 -exportXMP "D:\make2\config\exportXMP.config.xml" -exportReconstructionRegion "D:\153982\153982.rcbox" -selectImage "D:\153982\photo2/*" -enableTexturingAndColoring true -save "D:\153982\153982.rcproj"
+
+
+%bin% -delegateTo 155686 -defineDistance 36h11:007 36h11:008 0.21 -align -align -update -setReconstructionRegionOnCPs 36h11:001 36h11:002 36h11:004 2.1 -moveReconstructionRegion 0 0 -2.1 -rotateReconstructionRegion 180 0 180 -setGroundPlaneFromReconstructionRegion -scaleReconstructionRegion 1.8 1.6 2.1 absolute center -moveReconstructionRegion 0 0 0.0025 -exportXMP "D:\make2\config\exportXMP.config.xml" -exportControlPointsMeasurements "D:\155686\155686.controlPoints.csv" "D:\make2\config\exportControlPoints.config.xml" -exportReconstructionRegion "D:\155686\155686.rcbox" -selectImage "D:\155686\photo2\*" -enableTexturingAndColoring true -save "D:\155686\155686.rcproj"
+
+%bin% -delegateTo 155686 -defineDistance 36h11:007 36h11:008 0.21 -defineDistance 36h11:002 36h11:004 1 -defineDistance 36h11:004 36h11:003 1 -defineDistance 36h11:003 36h11:001 1 -align -align -update -setReconstructionRegionOnCPs 36h11:001 36h11:002 36h11:003 2.1 -moveReconstructionRegion 0 0 -2.1 -rotateReconstructionRegion 180 0 180 -setGroundPlaneFromReconstructionRegion -scaleReconstructionRegion 1.8 1.6 2.1 absolute center -moveReconstructionRegion 0 0 0.0025 -exportXMP "D:\make2\config\exportXMP.config.xml" -exportControlPointsMeasurements "D:\155686\155686.controlPoints.csv" "D:\make2\config\exportControlPoints.config.xml" -exportReconstructionRegion "D:\155686\155686.rcbox" -selectImage "D:\155686\photo2\*" -enableTexturingAndColoring true -save "D:\155686\155686.rcproj"
+
+
+
+%bin% -delegateTo 158508 -defineDistance 36h11:007 36h11:008 0.21 -align -align -update -setReconstructionRegionOnCPs 36h11:001 36h11:002 36h11:004 2.1 -moveReconstructionRegion 0 0 -2.1 -rotateReconstructionRegion 180 0 180 -setGroundPlaneFromReconstructionRegion -scaleReconstructionRegion 1.8 1.6 2.1 absolute center -moveReconstructionRegion 0 0 0.0025 -exportXMP "D:\make2\config\exportXMP.config.xml" -exportControlPointsMeasurements "D:\158508\158508.controlPoints.csv" "D:\make2\config\exportControlPoints.config.xml" -exportReconstructionRegion "D:\158508\158508.rcbox" -selectImage "D:\158508\photo2\*" -enableTexturingAndColoring true -save "D:\158508\158508.rcproj"
+
+
+
+
+%bin% -delegateTo 161086 -defineDistance 36h11:007 36h11:008 0.21 -align -align -update -setReconstructionRegionOnCPs 36h11:001 36h11:002 36h11:004 2.1 -moveReconstructionRegion 0 0 -2.1 -rotateReconstructionRegion 180 0 180 -setGroundPlaneFromReconstructionRegion -scaleReconstructionRegion 1.8 1.6 2.1 absolute center -moveReconstructionRegion 0 0 0.0025 -exportXMP "D:\make2\config\exportXMP.config.xml" -exportControlPointsMeasurements "D:\161086\161086.controlPoints.csv" "D:\make2\config\exportControlPoints.config.xml" -exportReconstructionRegion "D:\161086\161086.rcbox" -selectImage "D:\161086\photo2\*" -enableTexturingAndColoring true -save "D:\161086\161086.rcproj"
\ No newline at end of file