#!/usr/bin/python import oss2, os, sys, redis, time, cv2, numpy, piexif, requests, shlex, subprocess, datetime, shutil, json, psutil from threading import Thread from matplotlib import pyplot as plt from PIL import Image, ImageEnhance 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 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 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 diff_time(start_time, end_time): d = end_time - start_time m = d.microseconds return str(d.seconds // 60) + ":" + str(d.seconds % 60) + ":" + str(m)[:-3] def down_from_oss(pid): start_time = datetime.datetime.now() path = os.path.join(workdir, pid) if os.path.exists(path): return os.makedirs(path) os.mkdir(os.path.join(path, 'photo1')) os.mkdir(os.path.join(path, 'photo2')) psid = getPSid(pid) # 根据前缀获取文件列表 prefix = f'photos/{pid}/' filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix) for file in filelist: filename = file.key.split('/')[-1] if psid == '9' and filename in ('135_8.jpg', '135_1.jpg'): continue if psid == '16' and filename in ('92_8.jpg', '92_1.jpg'): continue if psid == '25' and filename in ('13_8.jpg', '13_1.jpg'): continue if psid == '34' and filename in ('154_8.jpg', '154_1.jpg'): continue if psid == '44' and filename in ('31_8.jpg', '31_1.jpg'): continue if psid == '63' and filename in ('123_8.jpg', '123_1.jpg'): continue if psid == '70' and filename in ('73_8.jpg', '73_1.jpg'): continue print('正在下载:', file.key) if not filename.endswith('jpg'): continue if filename.endswith('_1.jpg'): localfile = os.path.join(path, 'photo1', filename) else: localfile = os.path.join(path, 'photo2', filename) oss_client.get_object_to_file(file.key, localfile) print('下载完成') end_time = datetime.datetime.now() print('下载耗时:', diff_time(start_time, end_time)) def down_xmps_from_oss(psid): def need_down(): filename = f'xmps/{psid}/{psid}.rcbox' if not oss_client.object_exists(filename): print(f'未找到{filename}, 请检查是否已经上传{psid}号影棚坐标文件') time.sleep(5) return False oss_file_last_modified = float(oss_client.get_object_meta(filename).last_modified) local_file = os.path.join(config_path, 'xmps', psid, f'{psid}.rcbox') if not os.path.exists(local_file): print(f'未找到{local_file}, 需要下载影棚坐标文件') os.makedirs(os.path.join(config_path, 'xmps', psid), exist_ok=True) oss_client.get_object_to_file(filename, local_file) return True local_file_last_modified = os.path.getmtime(local_file) if oss_file_last_modified > local_file_last_modified: print(f'本地{local_file}文件已过期, 需要下载影棚坐标文件') oss_client.get_object_to_file(filename, local_file) return True if not need_down(): return print('正在下载影棚坐标文件') dest_path = os.path.join(config_path, 'xmps', psid) os.makedirs(os.path.join(dest_path, 'mesh'), exist_ok=True) os.makedirs(os.path.join(dest_path, 'texture'), exist_ok=True) prefix = f'xmps/{psid}/mesh/' filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix) for file in filelist: if file.key.endswith('.xmp'): filename = file.key.split('/')[-1] print('正在下载:', file.key) oss_client.get_object_to_file(file.key, os.path.join(dest_path, 'mesh', filename)) prefix = f'xmps/{psid}/texture/' filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix) for file in filelist: if file.key.endswith('.xmp'): filename = file.key.split('/')[-1] print('正在下载:', file.key) oss_client.get_object_to_file(file.key, os.path.join(dest_path, 'texture', filename)) print('下载完成') 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 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(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(pid): start_time = datetime.datetime.now() 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 os.makedirs(os.path.join(workdir, pid, 'photo3'), exist_ok=True) 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("Done") end_time = datetime.datetime.now() print('调整照片耗时:', diff_time(start_time, end_time)) return True def get_ps_type(pid): # return 1:圆形影棚 2:方形影棚 res = requests.get(get_ps_type_url, params={'pid': pid}) return res.json()['data']['type'] def getPSid(pid): res = requests.get(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(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 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 = oss_client.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 = oss_client.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 set_photos_join_type(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 rc_make(pid, psid, key): status = True # 建模 start = datetime.datetime.now() xmps_mesh_path = config_path + f'xmps\\{psid}\\mesh\\' xmps_texture_path = config_path + f'xmps\\{psid}\\texture\\' input_path = os.path.join(workdir, pid) output_path = os.path.join(input_path, 'output') ImagesGeometry = os.path.join(input_path, "photo1") ImagesTexture = os.path.join(input_path, "photo2") photo3 = os.path.join(input_path, "photo3") ps_region = os.path.join(config_path, 'xmps', psid, f'{psid}.rcbox') shutil.rmtree(output_path, ignore_errors=True) os.system('mkdir ' + output_path) ps_fix_list = ('10', '12', '13', '16', '18', '19', '20', '22', '23', '29', '30', '31') os.system('xcopy /Y ' + xmps_mesh_path + '* ' + ImagesGeometry) os.system('xcopy /Y ' + xmps_texture_path + '* ' + ImagesTexture) simplify_value = str(getHeadCount(pid) * 100 * 10000) if aliyun_face(pid) and get_ps_type(pid) == 1: calulate_type = 'calculateHighModel' else: calulate_type = 'calculateNormalModel' if adjust_photos(pid): print('已调整照片,产生出photo3图片组,让photo1和photo2参与建模,photo3仅参与贴图') # os.system('xcopy /Y ' + xmps_texture_path + '* ' + photo3) set_photos_join_type(pid, 'photo1', mesh='1', texture='0') set_photos_join_type(pid, 'photo2', mesh='1', texture='0') # set_photos_join_type(pid, 'photo3', mesh='0', texture='1') print('rcver:', get_rcver()) if get_rcver() == 2: cmd = rcbin + \ ' -disableOnlineCommunication ' + \ ' -setInstanceName ' + pid + \ ' -addFolder "' + ImagesGeometry + '"' + \ ' -selectAllImages -enableTexturingAndColoring false ' + \ ' -set "sfmEnableCameraPrior=True" -set "sfmMaxFeaturesPerMpx=20000" -set "sfmMaxFeaturesPerImage=200000" -set "sfmImagesOverlap=High" -set "MvsDoCorrectColors=false" -set "MvsIgnoreCorrectColors=false" -set "sfmMaxFeatureReprojectionError=1" ' + \ ' -align ' + \ ' -addFolder "' + ImagesTexture + '" -selectAllImages -enableTexturingAndColoring false ' + \ ' -align ' + \ ' -addFolder "' + photo3 + '" ' + \ ' -align -align ' + \ ' -setReconstructionRegion "' + ps_region + '" ' + \ ' -setGroundPlaneFromReconstructionRegion ' + \ ' -set "mvsMinSampleDistance=0.00001" ' + \ ' -' + calulate_type + ' ' + \ ' -selectLargestModelComponent -invertTrianglesSelection -removeSelectedTriangles -closeHoles -cleanModel ' + \ ' -smooth ' + \ ' -simplify ' + simplify_value + ' ' + \ ' -calculateTexture ' + \ ' -exportSelectedModel "' + output_path + '\\' + pid + '.obj" "' + config_path + 'ModelExportParams.xml" ' + \ ' -quit' else: cmd = rcbin + \ ' -disableOnlineCommunication ' + \ ' -silent ' + output_path + \ ' -addFolder "' + ImagesGeometry + '"' + \ ' -set "sfmMaxFeaturesPerMpx=20000" -set "sfmMaxFeaturesPerImage=200000" -set "sfmImagesOverlap=High" -set "sfmMaxFeatureReprojectionError=1" ' + \ ' -align ' + \ ' -addFolder "' + ImagesTexture + '"' + \ ' -align ' + \ ' -addFolder "' + photo3 + '"' + \ ' -align -align' + \ ' -setReconstructionRegion "' + ps_region + '" ' + \ ' -mvs ' + \ ' -modelSelectMaximalConnectedComponent -modelInvertSelection -modelRemoveSelectedTriangles -closeHoles -clean ' + \ ' -simplify ' + simplify_value + ' ' + \ ' -smooth -unwrap ' + \ ' -calculateTexture ' + \ ' -renameModel ' + pid + ' ' + \ ' -exportModel ' + pid + ' "' + output_path + '\\' + pid + '.obj" "' + config_path + 'ModelExportParams102.xml" ' + \ ' -quit' else: print('未调整照片,仍然使用photo1和photo2建模,photo2参与贴图模式') set_photos_join_type(pid, 'photo1', mesh='1', texture='0') set_photos_join_type(pid, 'photo2', mesh='1', texture='1') if get_rcver() == 2: cmd = rcbin + \ ' -disableOnlineCommunication ' + \ ' -setInstanceName ' + pid + \ ' -addFolder "' + ImagesGeometry + '"' + \ ' -selectAllImages -enableTexturingAndColoring false ' + \ ' -set "sfmEnableCameraPrior=True" -set "sfmMaxFeaturesPerMpx=20000" -set "sfmMaxFeaturesPerImage=200000" -set "sfmImagesOverlap=High" -set "MvsDoCorrectColors=false" -set "MvsIgnoreCorrectColors=false" -set "sfmMaxFeatureReprojectionError=1" ' + \ ' -align ' + \ ' -addFolder "' + ImagesTexture + '"' + \ ' -align -align' + \ ' -selectMaximalComponent ' + \ ' -importGroundControlPoints "' + config_path + 'GCPsDetectedMarkers.txt" "' + config_path + 'GCPImportParams.xml" ' + \ ' -setReconstructionRegion "' + ps_region + '" ' + \ ' -setGroundPlaneFromReconstructionRegion ' + \ ' -set "mvsMinSampleDistance=0.00001" ' + \ ' -' + calulate_type + ' ' + \ ' -selectLargestModelComponent -invertTrianglesSelection -removeSelectedTriangles -closeHoles -cleanModel ' + \ ' -smooth ' + \ ' -simplify ' + simplify_value + ' ' + \ ' -calculateTexture ' + \ ' -exportSelectedModel "' + output_path + '\\' + pid + '.obj" "' + config_path + 'ModelExportParams.xml" ' + \ ' -quit' else: cmd = rcbin + \ ' -disableOnlineCommunication ' + \ ' -silent ' + output_path + \ ' -addFolder "' + ImagesGeometry + '"' + \ ' -set "sfmMaxFeaturesPerMpx=20000" -set "sfmMaxFeaturesPerImage=200000" -set "sfmImagesOverlap=High" -set "sfmMaxFeatureReprojectionError=1" ' + \ ' -align ' + \ ' -addFolder "' + ImagesTexture + '"' + \ ' -align -align' + \ ' -setReconstructionRegion "' + ps_region + '" ' + \ ' -mvs ' + \ ' -modelSelectMaximalConnectedComponent -modelInvertSelection -modelRemoveSelectedTriangles -closeHoles -clean ' + \ ' -simplify ' + simplify_value + ' ' + \ ' -smooth -unwrap ' + \ ' -calculateTexture ' + \ ' -renameModel ' + pid + ' ' + \ ' -exportModel ' + pid + ' "' + output_path + '\\' + pid + '.obj" "' + config_path + 'ModelExportParams102.xml" ' + \ ' -quit' print(cmd) cmd = shlex.split(cmd) res = subprocess.run(cmd) print(res) end = datetime.datetime.now() print('重建耗时:', diff_time(start, end)) return status def fix_mtl_file(pid): if os.path.exists(os.path.join(workdir, pid, 'output', f'{pid}_u0_v0_diffuse.jpg')): texture_filename_end = '_u0_v0_diffuse.jpg' elif os.path.exists(os.path.join(workdir, pid, 'output', f'{pid}_u1_v1.jpg')): texture_filename_end = '_u1_v1.jpg' path = os.path.join(workdir, pid) mtl_file = os.path.join(path, 'output', pid + '.mtl') os.rename(os.path.join(path, 'output', pid + texture_filename_end), os.path.join(path, 'output', pid + '.jpg')) with open(os.path.join(path, mtl_file), 'r') as f: lines = f.readlines() lines = [line.replace(texture_filename_end, '.jpg') for line in lines] with open(os.path.join(path, mtl_file), 'w') as f: f.writelines(lines) def delete_lines_in_file(filename, count): with open(filename, 'r') as f: lines = f.readlines() lines = lines[count:] with open(filename, 'w') as f: f.writelines(lines) def find_gray(img): gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = gray[2800:, :] hist = cv2.calcHist([gray], [0], None, [256], [0, 256]) plt.plot(hist) def find_color_area(img, lower_color, upper_color): color = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) color = color[2800:, :] mask = cv2.inRange(color, lower_color, upper_color) area = cv2.countNonZero(mask) return round(area / (color.shape[0] * color.shape[1]), 4) def clean_photo2(psid, pid): path = os.path.join(workdir, pid, 'photo2') print('正在处理psid:', psid, '的颜色配置:', config.ps_lights.get(psid)) if config.ps_lights.get(psid) is None: ps_lights = config.ps_lights['0'] else: ps_lights = config.ps_lights[psid] for filename in os.listdir(path): if not filename.endswith('_8.jpg'): continue img = cv2.imread(os.path.join(path, filename)) white_area = find_color_area(img.copy(), ps_lights['lower_white'], ps_lights['upper_white']) gray_area = find_color_area(img.copy(), ps_lights['lower_gray'], ps_lights['upper_gray']) print('file:', os.path.join(path, filename), 'white_area:', white_area, 'gray_area:', gray_area) if filename == '25_8.jpg': print('file:', os.path.join(path, filename), 'white_area:', white_area, 'gray_area:', gray_area) if white_area < gray_area or gray_area > ps_lights['gray_threshold']: print('删除亮度异常图片:', os.path.join(path, filename), '亮度:', white_area, '灰度:', gray_area) os.remove(os.path.join(path, filename)) def is_makeing(): for p in psutil.process_iter(['name']): if p.info['name'] == 'RealityCapture.exe': return True return False def resize_photos(pid, photoN, ratio, quality_value=90): path = os.path.join(workdir, photoN, pid) for file in os.listdir(path): if file.endswith('.jpg'): img = Image.open(os.path.join(path, file)) width, height = img.size img = img.resize((int(width*ratio), int(height*ratio))) img.save(os.path.join(path, file), optimize=True, quality=quality_value) print(f'调整{photoN}照片尺寸:{file} to {int(width*ratio)}x{int(height*ratio)} 完成') def auto_make_3d(r, key): while True: process_3d = False # 检测是否已经有任务在进行,没有的话处理一下3D相册建模队列 try: if r.llen('model:make_experience') == 0: time.sleep(5) if r.llen(key) == 0: time.sleep(5) continue else: pid = r.lpop(key) if pid is None: continue else: pid = r.lpop('model:make_experience') if pid is None: continue process_3d = True except Exception as e: print(e) time.sleep(5) r = redis.Redis(host='106.14.158.208', password='kcV2000', port=6379, db=6) continue pid = pid.decode('utf-8') psid = getPSid(pid) # 定义需要走新的建模流程的影棚,将建模任务加入新的本地队列,原有建模任务跳过 if libs_db.is_new_make_psids(psid): print(f'pid:{pid} psid:{psid} 需要走新的建模流程') if process_3d: task_type = 'make_experience' else: task_type = 'make' libs_db.add_task({"task_type": task_type, "task_key": pid,"psid":psid}) continue down_xmps_from_oss(psid) print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())), f'pid:{pid} 模型重建 start') res = requests.post(update_status_modeling_url, data={'id': pid}) print('更新建模中状态:', res.text) # 从oss下载图片 down_from_oss(pid) if process_3d: print(f'准备处理3D相册pid:{pid}的照片') resize_photos(pid, 'photo1', 0.5) resize_photos(pid, 'photo2', 0.5) # 调用rc建模 if rc_make(pid, psid, key): fix_mtl_file(pid) os.system(f'{blenderbin} -b -P d:\\apps\\blender\\autofix.py -- {pid}') os.system(f'gltfpack -c -i {os.path.join(workdir, pid, "output", pid + ".obj")} -o {os.path.join(workdir, pid, "output", pid + ".glb")}') print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())), f'pid:{pid} 建模完成,开始上传到oss') print('建模成功: ' + pid, '开始上传模型文件...') oss_client = oss2.Bucket(oss2.Auth(AccessKeyId, AccessKeySecret), Endpoint, Bucket) oss_client.put_object_from_file(f'objs/auto/{pid}/{pid}.obj.rcInfo', os.path.join(workdir, pid, 'output', pid + '.obj.rcInfo')) oss_client.put_object_from_file(f'objs/auto/{pid}/{pid}.obj', os.path.join(workdir, pid, 'output', pid + '.obj')) oss_client.put_object_from_file(f'objs/auto/{pid}/{pid}.mtl', os.path.join(workdir, pid, 'output', pid + '.mtl')) oss_client.put_object_from_file(f'objs/auto/{pid}/{pid}.jpg', os.path.join(workdir, pid, 'output', pid + '.jpg')) oss_client.put_object_from_file(f'glbs/auto/{pid}.glb', os.path.join(workdir, pid, 'output', pid + '.glb')) res = requests.post(update_status_modelsuccess_url, data={'id': pid}) print('上传完成更新建模成功状态:', res.text) print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'pid:{pid} 建模完成,上传模型及更新状态 end') else: print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'pid:{pid} 建模失败') # 建模失败,放回队列,微信通知技术人员介入处理 r.lpush(key, pid) res = requests.post(update_status_modelfailed_url, data={'id': pid}) # 清空本地缓存 shutil.rmtree(os.path.join(workdir, pid), ignore_errors=True) if get_rcver() == 1 : shutil.rmtree(temp_path, ignore_errors=True) time.sleep(1) if __name__ == '__main__': AccessKeyId = 'LTAI5tSReWm8hz7dSYxxth8f' AccessKeySecret = '8ywTDF9upPAtvgXtLKALY2iMYHIxdS' Endpoint = 'oss-cn-shanghai.aliyuncs.com' Bucket = 'suwa3d-securedata' oss_client = oss2.Bucket(oss2.Auth(AccessKeyId, AccessKeySecret), Endpoint, Bucket) r = redis.Redis(host='106.14.158.208', password='kcV2000', port=6379, db=6) update_status_modeling_url = 'https://mp.api.suwa3d.com/api/customerP3dLog/toModeling' update_status_modelsuccess_url = 'https://repair.api.suwa3d.com/api/modelRepairOrder/toModelMakeSucceed' update_status_modelfailed_url = 'https://mp.api.suwa3d.com/api/customerP3dLog/toModelMakeFailed' get_psid_url = 'https://mp.api.suwa3d.com/api/customerP3dLog/photoStudio' get_printinfo_url = 'https://mp.api.suwa3d.com/api/customerP3dLog/printInfo' update_status_printstatus_url = 'https://mp.api.suwa3d.com/api/customerP3dLog/updateBuildPrintModelStatus' get_ps_adjust_photo_para_url = 'https://mp.api.suwa3d.com/api/equipment/configForColor' # 获取ps调整图片参数的接口 get_ps_type_url = "https://mp.api.suwa3d.com/api/takephotoOrder/photoStudioInfo" # 获取ps类型的接口 workdir = 'D:\\' rcbin = '"C:\\Program Files\\Capturing Reality\\RealityCapture\\RealityCapture.exe"' blenderbin = find_blender_bin_path() config_path = 'D:\\apps\\config\\' temp_path = 'D:\\RealityCapture.Temp\\' print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), '3D重建程序 start ', ) key = 'model:make' if len(sys.argv) > 1: key = sys.argv[1] if key not in ['model:make', 'model:make10']: print('参数错误,只能是model:make或者model:make10') sys.exit(1) auto_make_3d(r, key)