建模程序 多个定时程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

340 lines
16 KiB

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)