51 changed files with 5187 additions and 61 deletions
Binary file not shown.
@ -0,0 +1,125 @@
@@ -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) |
||||
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
<Configuration id="{2D5793BC-A65D-4318-A1B9-A05044608385}"> |
||||
<entry key="eiExportImageList" value="true"/> |
||||
<entry key="eiNearPlaneDistance" value="0.0"/> |
||||
<entry key="calexUndistResMode" value="2"/> |
||||
<entry key="calexUndistPrincipal" value="true"/> |
||||
<entry key="calexTrans" value="0"/> |
||||
<entry key="eiExportFileNaming" value="5"/> |
||||
<entry key="calexHasDisabled" value="0x0"/> |
||||
<entry key="eiExportMasks" value="true"/> |
||||
<entry key="calexRequiresUndistortPrincipal" value="0x0"/> |
||||
<entry key="calexRequiresEqualResolution" value="0x0"/> |
||||
<entry key="calexDownscale" value="0x1"/> |
||||
<entry key="calexUndistMaxPixels" value="-1"/> |
||||
<entry key="eiExportImageListFileName" value="imageList.txt"/> |
||||
<entry key="calexUndistFitMode" value="2"/> |
||||
<entry key="eiFarPlaneDistance" value="1000000.0"/> |
||||
<entry key="hasCalexFilePath" value="1"/> |
||||
<entry key="calexHasUndistort" value="0"/> |
||||
<entry key="calexFileFormat" value="Export Depth and Mask Images"/> |
||||
<entry key="calexExportUndistorted" value="true"/> |
||||
<entry key="calexFileFormatId" value="{0ABB46B2-4FAA-4CE1-AA39-D96128D39BD9}"/> |
||||
<entry key="hasCalexFileName" value="0"/> |
||||
<entry key="calexUndistCutOut" value="1.0"/> |
||||
<entry key="calexHasImageExport" value="-1"/> |
||||
<entry key="eiExportDepths" value="true"/> |
||||
</Configuration> |
||||
@ -0,0 +1,206 @@
@@ -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") |
||||
@ -0,0 +1,90 @@
@@ -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 |
||||
@ -0,0 +1,124 @@
@@ -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) |
||||
@ -0,0 +1,340 @@
@@ -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) |
||||
@ -0,0 +1,267 @@
@@ -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) |
||||
@ -0,0 +1,185 @@
@@ -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) |
||||
@ -0,0 +1,27 @@
@@ -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 |
||||
@ -0,0 +1,28 @@
@@ -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 |
||||
@ -0,0 +1,393 @@
@@ -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 |
||||
@ -0,0 +1,307 @@
@@ -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 |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,28 @@
@@ -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 |
||||
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
<Configuration id="{2D5793BC-A65D-4318-A1B9-A05044608385}"> |
||||
<entry key="calexUndistResMode" value="2"/> |
||||
<entry key="calexTrans" value="1"/> |
||||
<entry key="calexUndistortNaming" value="5"/> |
||||
<entry key="calexUndistortPixelFormat" value="24bppBGR"/> |
||||
<entry key="calexHasDisabled" value="0x0"/> |
||||
<entry key="calexRequiresUndistortPrincipal" value="0x1"/> |
||||
<entry key="calexExportImages" value="true"/> |
||||
<entry key="calexUndistortImageFormat" value="jpg"/> |
||||
<entry key="MvsExportScaleZ" value="1.0"/> |
||||
<entry key="MvsExportIsGeoreferenced" value="0x0"/> |
||||
<entry key="MvsExportIsModelCoordinates" value="0"/> |
||||
<entry key="calexRequiresColorCorrection" value="0x0"/> |
||||
<entry key="MvsExportScaleY" value="1.0"/> |
||||
<entry key="calexDownscale" value="0x1"/> |
||||
<entry key="calexRequiresEqualResolution" value="0x0"/> |
||||
<entry key="calexUndistMaxPixels" value="0"/> |
||||
<entry key="calexInputHasLayers" value="0"/> |
||||
<entry key="MvsExportScaleX" value="1.0"/> |
||||
<entry key="calexUndistFitMode" value="2"/> |
||||
<entry key="MvsExportRotationY" value="0.0"/> |
||||
<entry key="MvsExportcoordinatesystemtype" value="0"/> |
||||
<entry key="MvsExportNormalFlipZ" value="false"/> |
||||
<entry key="MvsExportRotationX" value="0.0"/> |
||||
<entry key="hasCalexFilePath" value="1"/> |
||||
<entry key="calexFolderCustom" value="false"/> |
||||
<entry key="MvsExportNormalFlipY" value="false"/> |
||||
<entry key="MvsExportNormalSpace" value="Mikktspace"/> |
||||
<entry key="calexHasUndistort" value="2"/> |
||||
<entry key="MvsExportNormalFlipX" value="false"/> |
||||
<entry key="MvsExportRotationZ" value="0.0"/> |
||||
<entry key="calexFileFormat" value="Bundler v0.3"/> |
||||
<entry key="MvsExportMoveZ" value="0.0"/> |
||||
<entry key="calexFileFormatId" value="{ECC4131A-1665-466C-93BE-66DF2EBC9086}"/> |
||||
<entry key="hasCalexFileName" value="1"/> |
||||
<entry key="calexUndistCutOut" value="1.0"/> |
||||
<entry key="calexHasImageExport" value="1"/> |
||||
<entry key="calexUndistBackColor" value="0"/> |
||||
<entry key="MvsExportMoveX" value="0.0"/> |
||||
<entry key="MvsExportNormalRange" value="ZeroToOne"/> |
||||
<entry key="MvsExportMoveY" value="0.0"/> |
||||
</Configuration> |
||||
@ -0,0 +1,13 @@
@@ -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" |
||||
|
||||
@ -0,0 +1,83 @@
@@ -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)}") |
||||
@ -0,0 +1,30 @@
@@ -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 '' |
||||
@ -0,0 +1,101 @@
@@ -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) |
||||
@ -0,0 +1,499 @@
@@ -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, |
||||
@ -0,0 +1,5 @@
@@ -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' |
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -1,15 +1,18 @@
@@ -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}%") |
||||
# 使用示例 |
||||
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') |
||||
|
||||
@ -0,0 +1,74 @@
@@ -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}") |
||||
@ -0,0 +1,8 @@
@@ -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) |
||||
@ -0,0 +1,102 @@
@@ -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 |
||||
@ -0,0 +1,43 @@
@@ -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 |
||||
@ -0,0 +1,6 @@
@@ -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" |
||||
@ -0,0 +1,381 @@
@@ -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) |
||||
@ -0,0 +1,31 @@
@@ -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) |
||||
|
||||
@ -0,0 +1,244 @@
@@ -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) |
||||
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
open3d |
||||
numpy |
||||
sklearn |
||||
argparse |
||||
bpy |
||||
@ -0,0 +1,78 @@
@@ -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) |
||||
@ -0,0 +1,22 @@
@@ -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() |
||||
@ -1,3 +1,42 @@
@@ -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 |
||||
%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" |
||||
Loading…
Reference in new issue