Files
make2/yj_local_build/main_step1.py
T
2024-12-27 10:43:26 +08:00

233 lines
11 KiB
Python

import os, sys, time, shlex, subprocess, shutil, requests, cv2, numpy as np
from PIL import Image
import json
with open('config.json', 'r') as f:
config = json.load(f)
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 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 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},将不参与贴图')
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} 射灯异常图片检测完成,共费时{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()
textpicCmd ='-selectImage "'+os.path.join(config['workdir'],pid,'photo2')+'\*" -enableTexturingAndColoring true'
#获取当前的工作目录
dirCurr = os.getcwd()
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")}" \
-align -selectAllImages \
-detectMarkers "{dirCurr}\detectMarkers.config.xml" \
-defineDistance 36h11:001 36h11:002 1 -defineDistance 36h11:002 36h11:004 1 -defineDistance 36h11:004 36h11:003 1 -defineDistance 36h11:003 36h11:001 1 -align -align -update {config["r2"]["setRegion"]} \
-exportXMP "{dirCurr}\exportXMP.config.xml" \
-exportControlPointsMeasurements "{os.path.join(config["workdir"], pid, f"{pid}.controlPoints.csv")}" "{dirCurr}\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} 定位点检测完成, 共费时{diff_time(start_time)}')
def step1(pid,headsCount):
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 开始处理{pid}建模任务')
start_time = time.time()
# 检测图片定位点,定位异常及时上报微信通知给客服人员,人工判断是否需要重新拍摄或更换地贴。定义定位点距离,导出相机位姿信息
detect_markers(0, pid)
# 处理图片,检测photo2中的异常图片不参与贴图,以免破坏贴图效果,默认不检测射灯异常图片,以节省算力成本
filter_dark_texture_image(pid)
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} {pid} step1图片预处理完成,共费时{diff_time(start_time)}')
# os.system(f'python {os.getcwd()}/main_step2.py {pid}')
step2(pid,headsCount)
def step2(pid,headsCount):
dirCurr = os.getcwd()
simplify_value = 1000000 * int(headsCount)
calulate_type = 'calculateNormalModel'
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")}" "{dirCurr}\\ModelExportParams.xml" -quit'
print(cmd)
cmd = shlex.split(cmd)
res = subprocess.run(cmd)
#阻塞判断是否导出完成
while True:
#判断 output 目录下是否存在 三个文件
files = os.listdir(os.path.join(config['workdir'], pid, "output"))
if len(files) >= 3:
break
#将导出的文件移动到指定目录
sourceDir = config["local_complate_build"]
#判断目录是否存在,不存在就创建
if not os.path.exists(sourceDir):
os.makedirs(sourceDir)
#将 output 目录里的文件移动到指定目录
shutil.move(os.path.join(config['workdir'], pid, "output"),os.path.join(sourceDir,pid))
#发起请求告知后端建模完成
try:
res = requests.post(url, data={'id': pid,'status':5000})
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid:{pid} 任务完成- {res.text}')
except Exception as e:
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid:{pid} - 建模完成状态变更失败 - {e}')
def main(pid,headsCount):
step1(pid, headsCount)
if __name__ == '__main__':
try:
url = config['urls']['update_status_modelsuccess_url']
if url == "":
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 请配置建模完成回调地址')
exit()
# 取云端redis任务,完成第一步的数据预处理后,将数据放入共享存储目录,将第二步任务塞入本地mysql队列
# 默认循环值守,可传参数运行单一任务,以方便调试
pid = '0'
if len(sys.argv) == 3:
pids = sys.argv[1].split(',')
headsCount = sys.argv[2]
for pid in pids:
main(pid,headsCount)
exit()
#获取文件夹下的所有文件
needBuildDir = config['local_need_build']
workdir = config['workdir']
if workdir == '':
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 请配置建模工作目录')
exit()
#不存在就创建工作目录
if not os.path.exists(workdir):
os.makedirs(workdir)
if not os.path.exists(needBuildDir):
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 需要建模目录不存在- {needBuildDir}')
exit()
except Exception as e:
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 初始化异常 - {e}')
#遍历文件夹下的所有文件进行处理
try:
while True:
time.sleep(5)
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 建模任务循环开始')
for pid in os.listdir(needBuildDir):
if not os.path.isdir(os.path.join(needBuildDir,pid)):
continue
#判断是否存在 canDo.txt 文件,如果不存在就跳过
if not os.path.exists(os.path.join(needBuildDir,pid,"canDo.txt")):
continue
#读取 canDo.txt 文件内容
headsCounts = 1
with open(os.path.join(needBuildDir,pid,"canDo.txt"),"r") as f:
headsCounts = f.read()
#判断文件夹里是否存在 do.txt , 如果存在就跳过,不存在就创建
if os.path.exists(os.path.join(needBuildDir,pid,"do.txt")):
continue
else:
with open(os.path.join(needBuildDir,pid,"do.txt"),"w") as f:
f.write("1")
#判断是否已经存在了,存在就删除
if os.path.exists(os.path.join(workdir,pid)):
shutil.rmtree(os.path.join(workdir,pid))
#将文件夹移动到工作目录
shutil.move(os.path.join(needBuildDir,pid),os.path.join(workdir,pid))
#执行建模流程,建模中的流程
try:
requests.post(url, data={'id': pid,'status':4000})
except Exception as e:
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid:{pid} - 状态变更失败 - {e}')
#continue
main(pid,headsCounts)
except Exception as e:
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 建模任务循环异常 - {e}')
exit()