From f20f6f3c342b33e802f01504523104e5d28f5c3f Mon Sep 17 00:00:00 2001 From: dongchangxi <458593490@qq.com> Date: Fri, 27 Dec 2024 10:20:46 +0800 Subject: [PATCH] =?UTF-8?q?=E8=80=81=E5=BD=B1=E6=A3=9A=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=AF=B9=E9=BD=90=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- old_to_new_build/get_reg_info.py | 169 +++++++++++++++++++++++++++ old_to_new_build/tools_to_xmps.py | 186 ++++++++++++++++++++++++++++++ 2 files changed, 355 insertions(+) create mode 100644 old_to_new_build/get_reg_info.py create mode 100644 old_to_new_build/tools_to_xmps.py diff --git a/old_to_new_build/get_reg_info.py b/old_to_new_build/get_reg_info.py new file mode 100644 index 0000000..39a6fd7 --- /dev/null +++ b/old_to_new_build/get_reg_info.py @@ -0,0 +1,169 @@ +import os, sys, time, shutil, subprocess, shlex, json,oss2,redis +import platform +if platform.system() == 'Windows': + sys.path.append('e:\\libs\\') +else: + sys.path.append('/data/deploy/make3d/make2/libs/') +import tools_to_xmps +import config, libs, libs_db + +def get_xmps(psid,pid): + #从共享盘上下载对齐信息,判断是否有 + print(f"判断是否存在 {os.path.join(config.sharedir, 'xmps_rate', psid, 'texture')} -- {os.path.exists(os.path.join(config.sharedir, 'xmps_rate', psid, 'texture'))}") + if os.path.exists(os.path.join(config.sharedir, 'xmps_rate', psid, 'texture')) == False: + #从oss上下载对齐信息 + prefix = f'xmps_rate/{psid}/mesh/' + filelist = oss2.ObjectIteratorV2(config.oss_bucket, prefix=prefix) + for file in filelist: + if file.key.endswith('.xmp'): + filename = file.key.split('/')[-1] + print('正在下载:', file.key) + # os.makedirs(os.path.join(config.sharedir, 'xmps_rate', psid, 'mesh'), exist_ok=True) + config.oss_bucket.get_object_to_file(file.key, os.path.join(config.sharedir,'xmps_rate', 'mesh', filename)) + + prefix = f'xmps_rate/{psid}/texture/' + filelist = oss2.ObjectIteratorV2(config.oss_bucket, prefix=prefix) + for file in filelist: + if file.key.endswith('.xmp'): + filename = file.key.split('/')[-1] + print('正在下载:', file.key) + # os.makedirs(os.path.join(config.sharedir, 'xmps_rate', psid, 'texture'), exist_ok=True) + config.oss_bucket.get_object_to_file(file.key, os.path.join(config.sharedir,'xmps_rate', 'texture', filename)) + + #将共享盘的对齐信息复制到工作目录,photo1 和 photo2 + shutil.copytree(os.path.join(config.sharedir, 'xmps_rate', psid, 'mesh'), os.path.join(config.workdir, pid, 'photo1'),dirs_exist_ok=True) + shutil.copytree(os.path.join(config.sharedir, 'xmps_rate', psid, 'texture'), os.path.join(config.workdir, pid, 'photo2'),dirs_exist_ok=True) + else: + #将共享盘的对齐信息复制到工作目录,photo1 和 photo2 + shutil.copytree(os.path.join(config.sharedir, 'xmps_rate', psid, 'mesh'), os.path.join(config.workdir, pid, 'photo1'),dirs_exist_ok=True) + shutil.copytree(os.path.join(config.sharedir, 'xmps_rate', psid, 'texture'), os.path.join(config.workdir, pid, 'photo2'),dirs_exist_ok=True) + + print('下载xmps完成') + +#获取photo2 的对齐信息 +def get_photo2_align_info(pid): + pid = str(pid) + psid = libs.getPSid(pid) + + #判断是否存在该目录 + if os.path.exists(os.path.join(config.workdir, pid)) == False: + #下载照片 + libs.down_from_oss(config.oss_bucket, config.workdir, pid) + else: + #移除文件夹 + shutil.rmtree(os.path.join(config.workdir, pid), ignore_errors=True) + #下载照片 + libs.down_from_oss(config.oss_bucket, config.workdir, pid) + + #判断是否存在该目录 + print(f"影棚号:{psid} , {config.oss_bucket.object_exists(f'xmps_rate/{psid}/')}") + filename = f'xmps_rate/{psid}/{psid}.rcbox' + isRate = False + if not config.oss_bucket.object_exists(filename): + #提示是否进行 xmps_rate 文件夹的创建 + yes_or_not = input('当前该影棚没有对应的对齐坐标,是否创建?(y/n)') + if yes_or_not == 'y': + tools_to_xmps.create_rate_xmps(pid) + isRate = True + else: + sys.exit(0) + + #旋转图片 + if isRate == False: + print(f"旋转图片:{pid}") + tools_to_xmps.rateImages(pid) + + #下载对齐信息 + get_xmps(psid,pid) + + #执行对齐指令 + 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, "photo2")}" \ + -detectMarkers "D:\\make2\\config\\detectMarkers.config.xml" \ + {libs.get_defineDistances(psid)} -align -align -align -align \ + -exportRegistration "D://{pid}/reg/{pid}_registration.out" "D://make2/config/registration_export_config.xml" -quit' + print(cmd) + cmd = shlex.split(cmd) + res = subprocess.run(cmd) + + #遍历 D://{pid}/reg/ 目录下的文件 + for file in os.listdir(os.path.join(config.workdir, pid, 'reg')): + if file.endswith('.jpg'): + #记录到文本文件中 + print(f"记录文件:{file}") + with open(os.path.join(config.workdir, pid, 'reg', f'{pid}_imgList.txt'), 'a+') as f: + f.write(f"{os.path.join(config.workdir, pid, 'photo2', file)}\n") + + + #遍历 reg 目录 上传到oss 上制定的目录 + for file in os.listdir(os.path.join(config.workdir, pid, 'reg')): + if not file.endswith('.jpg'): + print(f'上传文件:{file}') + config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/repeat_build/{file}', os.path.join(config.workdir, pid, 'reg', file)) + else: + print(f'上传文件:{file}') + #上传到指定的目录 + config.oss_bucket.put_object_from_file(f'objs/auto/{pid}/repeat_build/jpgs/{file}', os.path.join(config.workdir, pid, 'reg', file)) + + #处理完成后塞入到指定的队列 + r = create_redis_connection() + r.rpush('ai:ai_repeat_build',pid) + + +def create_redis_connection(): + """创建 Redis 连接,若连接失败则重试""" + while True: + try: + r = redis.Redis(host="106.14.158.208", password="kcV2000", port=6379, db=6) + # 尝试进行一次操作,检查连接是否有效 + r.ping() # ping 操作是一个简单的连接测试 + print("Redis连接成功!") + return r + except ConnectionError: + print("Redis连接失败,正在重试...") + time.sleep(5) + + +if __name__ == '__main__': + start = time.time() + if len(sys.argv) == 2: + pids = sys.argv[1] + for pid in pids.split(','): + get_photo2_align_info(pid) + print(f'{pid}共费时{time.time() - start}秒') + else: + r = create_redis_connection() # 使用重连函数来创建连接 + while True: + try: + if r.llen('ai:ai_repeat_for_align_info') == 0: + print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+"-没有查询到重建任务在队列中,等待10s在查询") + time.sleep(10) + continue + + pid = r.lpop('ai:ai_repeat_for_align_info') + #判断是否为空 + if pid is None: + print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+"-读取的PID为空") + continue + #判断是否为数字 + try: + pid = int(pid.decode('utf-8')) + except Exception as e: + print(f'pid:{pid} 不是数字') + continue + + #执行任务 + get_photo2_align_info(pid) + print(f'{pid}共费时{time.time() - start}秒') + continue + except Exception as e: + print(f'出现异常:{e}') + time.sleep(30) + r = create_redis_connection() + continue + + + + + \ No newline at end of file diff --git a/old_to_new_build/tools_to_xmps.py b/old_to_new_build/tools_to_xmps.py new file mode 100644 index 0000000..7ddfc33 --- /dev/null +++ b/old_to_new_build/tools_to_xmps.py @@ -0,0 +1,186 @@ +import os, sys, time, shutil, subprocess, shlex, json,oss2 +from PIL import Image +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 + + +#检测是否存在 rate_xmps 文件,如果没有则要创建该影棚对应的rate_xmps文件 +def check_rate_xmps(pid): + pid = str(pid) + psid = libs.getPSid(pid) + #判断是否存在该目录 + if config.oss_bucket.object_exists(f'xmps_rate/{psid}/') == False: + return False + return True + +def clearExifAndRotate(imagePath, rotate=180): + if os.path.exists(imagePath) == False: + print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {imagePath} 图片不存在') + return + + print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {imagePath} 图片exif信息清除并且旋转...') + # img = Image.open(imagePath) + # print(img.info) + # # 清除 EXIF 信息 + # img.info = {} # 清除 EXIF 信息 + # # 旋转图片 180 度 + # img = img.rotate(180) + # # 保存处理后的图片 + # img.save(imagePath) + + # 打开图像 + with Image.open(imagePath) as img: + # 使用RGB模式打开图像来丢弃可能存在的EXIF信息 + img = img.convert("RGB") + img = img.rotate(180) + # 保存图像,保存时不会带有原始的任何元数据 + img.save(imagePath, quality=100) # 对于JPEG,可以调整质量参数 + + + +#如果老影棚没有做过旋转坐标的照片的,则要做一次旋转坐标 +def rateImages(pid): + #遍历文件夹下的所有图片 + photo1_path = os.path.join(config.workdir, pid, 'photo1') + photo2_path = os.path.join(config.workdir, pid, 'photo2') + for pic in os.listdir(photo1_path): + if pic.endswith('.jpg'): + #清除图片exif信息, 旋转图片 180度 + clearExifAndRotate(os.path.join(photo1_path, pic)) + print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pic} 图片exif信息清除并且旋转完成') + + for pic in os.listdir(photo2_path): + if pic.endswith('.jpg'): + #清除图片exif信息, 旋转图片 180度 + clearExifAndRotate(os.path.join(photo2_path, pic)) + print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pic} 图片exif信息清除并且旋转完成') + + print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} 图片exif信息清除并且旋转完成') + + +def upload_xmp(pid): + print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 上传xmp文件之前先删除oss上的xmps_rate文件所在目录...') + pid = str(pid) + psid = libs.getPSid(pid) + #移除掉旧的文件夹 + #config.oss_bucket.delete_object(f'xmps/{pid}/') + #删除oss 上的文件夹里的内容 + + #判断是否存在该目录 + if config.oss_bucket.object_exists(f'xmps_rate/{psid}/') == True: + object_list = oss2.ObjectIterator(config.oss_bucket, prefix=f'xmps_rate/{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) + + config.oss_bucket.put_object_from_file(f'xmps_rate/{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_rate/{psid}/mesh/{xmp}', os.path.join(workdir, 'photo1', xmp)) + #复制一份到共享盘上的 libs xmps psid 文件夹下 + #判断是否有对应的文件夹,不存在就创建 + os.makedirs(os.path.join(config.sharedir, 'xmps_rate', psid, 'mesh'), exist_ok=True) + + shutil.copy(os.path.join(workdir, 'photo1', xmp), os.path.join(config.sharedir, 'xmps_rate', psid, 'mesh', xmp)) + + for xmp in os.listdir(os.path.join(workdir, 'photo2')): + if xmp.endswith('.xmp'): + config.oss_bucket.put_object_from_file(f'xmps_rate/{psid}/texture/{xmp}', os.path.join(workdir, 'photo2', xmp)) + #复制一份到共享盘上的 libs xmps psid 文件夹下 + os.makedirs(os.path.join(config.sharedir, 'xmps_rate', psid, 'texture'), exist_ok=True) + shutil.copy(os.path.join(workdir, 'photo2', xmp), os.path.join(config.sharedir, 'xmps_rate', psid, 'texture', xmp)) + + print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} xmp文件上传完成,共费时{time.time() - start_time}秒') + + +#创建rate_xmps文件 +def create_rate_xmps(pid): + start_time = time.time() + pid = str(pid) + psid = libs.getPSid(pid) + #判断是否存在xmps_rate文件夹 + flag = check_rate_xmps(pid) + if flag == True: + # 提示输入指令是否要重新做rate_xmps文件 + print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} rate_xmps文件已经存在,是否重新生成rate_xmps文件?') + continue_or_not = input('是否重新生成rate_xmps文件?(y/n)') + if continue_or_not == 'y': + pass + else: + sys.exit(0) + + #判断是否有对应的 photo1 和 photo2 文件夹 + photo1_path = os.path.join(config.workdir, pid, 'photo1') + photo2_path = os.path.join(config.workdir, pid, 'photo2') + + #判断是否存在目录 + if os.path.exists(photo1_path) == False or os.path.exists(photo2_path) == False: + #重新下载图片文件photo1和photo2 + libs.down_from_oss(config.oss_bucket, config.workdir, pid) + + 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) + + #清除图片exif信息, 旋转图片 180度 + rateImages(pid) + #通过rc 计算出 xmps 文件 + 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")}"' + 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)}') + + + upload_or_not = input('是否上传oss?(y/n)') + if upload_or_not == 'y': + upload_xmp(pid) + + print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} rate_xmps文件生成完成,共费时{libs.diff_time(start_time)}') + + +if __name__ == '__main__': + pid = sys.argv[1] + print(f'执行任务的pid: {pid}') + create_rate_xmps(pid) +