Browse Source

建模相关功能的修改

master
dongchangxi 2 years ago
parent
commit
04852e95cd
  1. 2
      doc/install.txt
  2. 27
      libs/common.py
  3. 86
      libs/computerRecboxCenterByPoint.py
  4. 31
      main_step2.py
  5. 5
      timer/get_task_to_db.py
  6. 76
      timer/setup_oem_exe.py
  7. 60
      tools/auto_distance.py

2
doc/install.txt

@ -2,7 +2,7 @@ pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
pip config set install.trusted-host pypi.tuna.tsinghua.edu.cn pip config set install.trusted-host pypi.tuna.tsinghua.edu.cn
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install oss2 redis pillow numpy opencv-python bpy tqdm pyautogui psutil pywin32 pymysql pip install oss2 redis pillow numpy opencv-python bpy tqdm pyautogui psutil pywin32 pymysql open3d scipy matplotlib
config config

27
libs/common.py

@ -138,6 +138,27 @@ def change_rcbox_deepth(pid,new_value):
with open(rcbox_path, 'w') as f: with open(rcbox_path, 'w') as f:
f.write(new_content) f.write(new_content)
def change_rcbox_center(pid,new_value):
rcbox_path = os.path.join(config.workdir, pid, f"{pid}.rcbox")
old_value_pattern = r'<center>(.*?)</center>'
#读取文件内容
with open(rcbox_path, 'r') as f:
content = f.read()
#使用正则表达式进行匹配
match = re.search(old_value_pattern,content)
if match:
old_value = match.group(1)
if old_value == "":
return
#分割字符串
arrStr = old_value.split(" ")
#重新拼接字符串
strs = arrStr[0]+" "+arrStr[1]+" "+str(new_value)
new_content = re.sub(old_value_pattern,f'<center>{strs}</center>',content)
#重新写入进去
with open(rcbox_path, 'w') as f:
f.write(new_content)
#修改rcproj文件,删除没有模型的component,保留最多model 的component #修改rcproj文件,删除没有模型的component,保留最多model 的component
def changeRcprojFile(pid): def changeRcprojFile(pid):
# 解析XML文件 # 解析XML文件
@ -224,6 +245,12 @@ def uploadControlPointsOss(pid):
#截屏保存 #截屏保存
def saveScreenImg(pid): def saveScreenImg(pid):
#判断pid 是否是数字
if str(pid).isdigit() == False:
return
if pid == 0 or pid == "":
return "pid 等于空"
#获取当前的日志 #获取当前的日志
if not os.path.exists(os.path.join(config.workdir,"screen", time.strftime("%y%m%d",time.localtime()))): if not os.path.exists(os.path.join(config.workdir,"screen", time.strftime("%y%m%d",time.localtime()))):
os.makedirs(os.path.join(config.workdir,"screen", time.strftime("%y%m%d",time.localtime()))) os.makedirs(os.path.join(config.workdir,"screen", time.strftime("%y%m%d",time.localtime())))

86
libs/computerRecboxCenterByPoint.py

@ -0,0 +1,86 @@
import open3d as o3d
import numpy as np
import matplotlib.pyplot as plt
import sys
import statistics
import math
import copy
import os,time
from scipy.stats import mode
from scipy.spatial import KDTree
from scipy.spatial import cKDTree
import matplotlib.font_manager as fm
#处理点云文件保存脚踝一下的部分点云
def dealPointData(pidPath,pidNewPath):
# 读取 PLY 文件
point_cloud = o3d.io.read_point_cloud(pidPath)
# 移除离散点
cl, ind = point_cloud.remove_statistical_outlier(nb_neighbors=20, std_ratio=0.06)
point_cloud = point_cloud.select_by_index(ind)
# 保存处理后的点云
o3d.io.write_point_cloud(pidNewPath, point_cloud)
data = np.loadtxt(pidNewPath)
# 提取xyz坐标
x = data[:, 0]
y = data[:, 1]
z = data[:, 2]
# 创建一个布尔索引,筛选出在x-y平面内,半径在0.5范围内的点 (z >= 0.00) &
mask = (z >=0) & (z <= 0.1) & (x**2 + y**2 <= 0.7**2)
# 根据索引,保留符合条件的点
filtered_data = data[mask]
# 将保留的点云数据保存到新的文件
np.savetxt(pidNewPath, filtered_data, delimiter=' ')
#计算点云的数据中,脚底和地板的切线位置
def boxCenter(pid):
pidPath = "D:\\xyz\\" + str(pid) + "_point.xyz"
pidNewPath = "D:\\xyz\\" + str(pid) + "_new.xyz"
dealPointData(pidPath,pidNewPath)
pcd = o3d.io.read_point_cloud(pidNewPath)
allPoints = np.asarray(pcd.points)
if len(allPoints) == 0:
print("点云为空,无法计算均值。")
return 0
# 使用RANSAC算法提取平面
plane_model, inliers = pcd.segment_plane(distance_threshold=0.00670, ransac_n=3, num_iterations=1000)
inlier_cloud = pcd.select_by_index(inliers)
# 获取被染成红色的点的坐标数组
red_points = inlier_cloud.points
red_points_np = np.asarray(red_points)
# 获取 red_points_np 的 z 值数组
z_red_values = red_points_np[:, 2]
# 计算中位数
medianRed = np.median(z_red_values)
# 计算中位数向上的平均数
meanRedUp = np.mean(z_red_values[z_red_values > medianRed])
#计算中位数向下的平均数
#meanRedDown = np.mean(z_red_values[z_red_values < medianRed])
# Exclude ground points from allPoints
foot_points_np = np.asarray([point for point in allPoints if point not in red_points_np])
if len(foot_points_np) == 0 :
print("脚部点云为空。")
return 0
#过滤掉地板,计算出脚底的点云数据
points_np_foot = foot_points_np[(foot_points_np[:, 2] < 0.046) & (foot_points_np[:, 2] > meanRedUp)]
# 计算平均值
mean = np.mean(points_np_foot[:, 2])
# 按照 Z 值进行排序
sorted_points = points_np_foot[np.argsort(points_np_foot[:, 2])]
# 获取 Z 值最低的前十个点
if len(sorted_points) == 0:
print("脚底板最低的点云为空")
return 0
try:
lowest_points = sorted_points[10:20]
except Exception as e:
print("获取脚底板最低的倒数第十到20的点出现异常错误")
return 0
# 计算平均值
meanLowEst = np.mean(lowest_points[:, 2]) + 1.05
return meanLowEst

31
main_step2.py

@ -6,7 +6,7 @@ if platform.system() == 'Windows':
#sys.path.append('libs') #sys.path.append('libs')
else: else:
sys.path.append('/data/deploy/make3d/make2/libs/') sys.path.append('/data/deploy/make3d/make2/libs/')
import config, libs, libs_db,common,main_service_db import config, libs, libs_db,common,main_service_db,computerRecboxCenterByPoint
redisLocal = config.redis_local redisLocal = config.redis_local
def load_model(pid): def load_model(pid):
cmd = f'{config.rcbin} {config.r1["init"]} -load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}"' cmd = f'{config.rcbin} {config.r1["init"]} -load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}"'
@ -116,9 +116,34 @@ def make3d(pid):
calulate_type = '-mvsHigh' calulate_type = '-mvsHigh'
else: else:
calulate_type = '-mvs' calulate_type = '-mvs'
#翻转相机的线向下
cmd = f'{config.rcbin} -load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" {cmdSmall} \ cmd = f'{config.rcbin} -load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" {cmdSmall} \
-set "sfmEnableCameraPrior=True" -align -set "sfmEnableCameraPrior=False" -align -save "{os.path.join(config.workdir, pid, f"{pid}_point.rcproj")}" '
cmd = shlex.split(cmd)
res = subprocess.run(cmd)
#执行完成后命令会触发导出点云的定时程序
while True:
print("判断是否导出点云文件循环阻塞开始")
time.sleep(3)
#判断是否有 pid_1 的的值
print(pid+"_3")
if redisLocal.lpos('model:auto_distance',pid+"_3") == None:
continue
shutil.move(os.path.join(config.workdir, pid, f'{pid}_point.rcproj'), os.path.join(config.workdir, pid, f'{pid}.rcproj'))
print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} pid: {pid} 导出点云文件完成')
#最后处理掉redis中的值
redisLocal.lrem('model:auto_distance', 0, pid+"_3")
break
#处理点云文件
centerRcboxValue = computerRecboxCenterByPoint.boxCenter(pid)
if centerRcboxValue > 0:
print("修改中心点的坐标",centerRcboxValue)
#修改中心点的值
common.change_rcbox_center(pid,centerRcboxValue)
cmd = f'{config.rcbin} -load "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" -align \
-set "sfmEnableCameraPrior=True" -align -set "sfmEnableCameraPrior=False" -align -setReconstructionRegion "{os.path.join(config.workdir, pid, f"{pid}.rcbox")}" \ -set "sfmEnableCameraPrior=True" -align -set "sfmEnableCameraPrior=False" -align -setReconstructionRegion "{os.path.join(config.workdir, pid, f"{pid}.rcbox")}" \
{calulate_type} -modelSelectMaximalConnectedComponent -modelInvertSelection -modelRemoveSelectedTriangles -closeHoles -clean -simplify {simplify_value} -smooth -unwrap -calculateTexture -renameModel {pid} -save "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" -quit' {calulate_type} -modelSelectMaximalConnectedComponent -modelInvertSelection -modelRemoveSelectedTriangles -closeHoles -clean -simplify {simplify_value} -smooth -unwrap -calculateTexture -renameModel {pid} -save "{os.path.join(config.workdir, pid, f"{pid}.rcproj")}" -quit'
print(cmd) print(cmd)

5
timer/get_task_to_db.py

@ -43,7 +43,10 @@ def readTask(key):
print("走新的建模系统不是分布式插入-重建工单",key,pid,psid) print("走新的建模系统不是分布式插入-重建工单",key,pid,psid)
libs_db.add_task(taskData) libs_db.add_task(taskData)
else: else:
if int(psid) <= 90 and int(psid) != 29 and int(psid) != 56: intPid = int(psid)
if intPid == 29 or intPid == 94 or intPid == 51:
libs_db.add_task(taskData)
elif int(psid) <= 90 and int(psid) != 29 and int(psid) != 56 and int(psid) != 1:
print("走分布式建模",key,pid,psid) print("走分布式建模",key,pid,psid)
if int(psid) == 41 or int(psid) == 85: if int(psid) == 41 or int(psid) == 85:
taskData["priority"] = 0 taskData["priority"] = 0

76
timer/setup_oem_exe.py

@ -0,0 +1,76 @@
import redis,requests,json,os,sys
import platform
if platform.system() == 'Windows':
sys.path.append('e:\\libs\\')
else:
sys.path.append('/data/deploy/make3d/make2/libs/')
import config
import requests
from PIL import Image
from io import BytesIO
def main():
#连接mp 的redis
r = redis.Redis(host="106.14.158.208",password="kcV2000",port=6379,db=1)
#取出数据
oemId = r.lpop('setup')
oemId = 21
if oemId is None:
print("没有从redis中获取到oemId的数据")
return
print("oemId",oemId)
#请求mp的接口,获取对应的oem的数据
res = requests.get("http://172.16.20.7:8199/api/oem/infoById",params={"id":oemId})
#获取数据解析数据
# print(res.text)
#解析数据
data = json.loads(res.text)
# print(data)
if data['code'] != 1000:
print("根据id获取oem数据失败")
return
print(data['data'])
#pythob 进入到 E:\wails\oemProject ,将 data 数据写入到 wails.json 文件中的 ext_oem 字段中
with open("D:\\oemProject\\wails.json","r",encoding="utf-8") as f:
wailsData = json.load(f)
wailsData['ext_oem'] = data['data']
wailsData['name'] = data['data']['brand_name']
wailsData["outputfilename"] = str(data['data']['id'])
with open("D:\\oemProject\\wails.json","w",encoding="utf-8") as f:
json.dump(wailsData,f,ensure_ascii=False,indent=4)
# #将图片下载到本地
getExeImg(data['data']['logo'], "D:\\oemProject\\build\\appicon.png")
#写入成功后在 E:\\wails\\oemProject\\ 目录下执行 wails build 命令
os.system("cd D:\\oemProject && wails build")
# #执行 wails build 命令后,将 E:\wails\oemProject\build\bin ,在上传到 oss 中
config.oss_bucket.put_object_from_file(f'exe/'+str(data['data']['id'])+".exe", "D:\\oemProject\\build\\bin\\"+str(data['data']['id'])+".exe")
print("上传成功")
# #上传成功后,调用接口,告诉mp,已经生成exe及上传成功
requests.get("http://172.16.20.7:8199/api/oem/infoSetupUpdate",params={"id":oemId})
def getExeImg(image_url, output_path):
# 从URL获取图片
response = requests.get(image_url)
if response.status_code == 200:
# 将内容读取为图片
image = Image.open(BytesIO(response.content))
# 修改图片尺寸为1024x1024
resized_image = image.resize((1024, 1024))
# 保存图片为PNG格式
resized_image.save(output_path, 'PNG')
else:
print(f"Failed to download image. Status code: {response.status_code}")
if __name__ == '__main__':
main()

60
tools/auto_distance.py

@ -28,10 +28,17 @@ def find_and_maximize_window(window_title):
pid = win32gui.GetWindowText(hwnd).split('screen')[0].split(' ')[0].split('-')[0].split('*')[0].split('_')[0] pid = win32gui.GetWindowText(hwnd).split('screen')[0].split(' ')[0].split('-')[0].split('*')[0].split('_')[0]
time.sleep(3) time.sleep(3)
#截屏 #截屏
if pid != "": if pid.isdigit():
common.saveScreenImg(pid) common.saveScreenImg(pid)
time.sleep(3) time.sleep(3)
ag.hotkey('alt', 'f4') ag.hotkey('alt', 'f4')
if "point" in win32gui.GetWindowText(hwnd):
pid = win32gui.GetWindowText(hwnd).split('screen')[0].split(' ')[0].split('-')[0].split('*')[0].split('_')[0]
time.sleep(5)
if pid != "":
print("开始导出导出点云文件")
exportPointColud(pid)
return '0', 0, 0, 0, 0 return '0', 0, 0, 0, 0
@ -59,6 +66,53 @@ def find_and_maximize_window(window_title):
# ag.typewrite(distance) # ag.typewrite(distance)
# ag.press('enter') # ag.press('enter')
#导出点云文件数据
def exportPointColud(pid):
#移动到alignment
ag.moveTo(177,33)
ag.click()
time.sleep(0.5)
#移动到Point cloud
ag.moveTo(850,85)
ag.click()
time.sleep(0.5)
#移动到弹出的框中的路径中,重写
ag.moveTo(739,186)
ag.click()
repeat_backspace(18)
time.sleep(0.5)
ag.typewrite("D:\\xyz")
ag.press('enter')
#输入文件的名称
time.sleep(0.5)
ag.moveTo(594,571)
ag.click()
repeat_backspace(15)
time.sleep(0.5)
ag.typewrite(str(pid)+"_point")
#保存按钮1
time.sleep(0.5)
ag.moveTo(1104,635)
ag.click()
time.sleep(0.5)
#保存按钮2
ag.moveTo(797,512)
ag.click()
time.sleep(2)
print("结束导出导出点云文件")
#退出
ag.hotkey('ctrl', 's') # save project
print("点击保存按钮")
time.sleep(5)
ag.hotkey('alt', 'f4') # close project
print("点击关闭按钮")
#加入pid+"_1"的队列
redisLocal.lpush('model:auto_distance', pid+"_3")
#去掉pid+"_0"的队列
redisLocal.lrem('model:auto_distance', 0, pid+"_1")
def get_defineDistances(pid, left, top, right, bottom): def get_defineDistances(pid, left, top, right, bottom):
psid = libs.getPSid(pid) psid = libs.getPSid(pid)
distances = libs_db.get_floor_sticker_distances(psid) #config.ps_floor_sticker.get(psid, config.ps_floor_sticker['default']) distances = libs_db.get_floor_sticker_distances(psid) #config.ps_floor_sticker.get(psid, config.ps_floor_sticker['default'])
@ -149,7 +203,9 @@ def defind_distance(pid, left, top, right, bottom):
time.sleep(5) time.sleep(5)
def main(): def main():
# time.sleep(6)
# exportPointColud()
# exit()
while True: while True:
time.sleep(1) time.sleep(1)
title = "wait" title = "wait"

Loading…
Cancel
Save