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
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) |