From 04852e95cdb42f414fb75032dc8de0bc41cf9301 Mon Sep 17 00:00:00 2001
From: dongchangxi <458593490@qq.com>
Date: Mon, 5 Feb 2024 16:04:17 +0800
Subject: [PATCH] =?UTF-8?q?=E5=BB=BA=E6=A8=A1=E7=9B=B8=E5=85=B3=E5=8A=9F?=
=?UTF-8?q?=E8=83=BD=E7=9A=84=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
doc/install.txt | 2 +-
libs/common.py | 27 +++++++++
libs/computerRecboxCenterByPoint.py | 86 +++++++++++++++++++++++++++++
main_step2.py | 31 ++++++++++-
timer/get_task_to_db.py | 5 +-
timer/setup_oem_exe.py | 76 +++++++++++++++++++++++++
tools/auto_distance.py | 60 +++++++++++++++++++-
7 files changed, 280 insertions(+), 7 deletions(-)
create mode 100644 libs/computerRecboxCenterByPoint.py
create mode 100644 timer/setup_oem_exe.py
diff --git a/doc/install.txt b/doc/install.txt
index 8cfb0f6..fad9f5f 100644
--- a/doc/install.txt
+++ b/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
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
diff --git a/libs/common.py b/libs/common.py
index 4a2fb20..3fb9839 100644
--- a/libs/common.py
+++ b/libs/common.py
@@ -138,6 +138,27 @@ def change_rcbox_deepth(pid,new_value):
with open(rcbox_path, 'w') as f:
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'
(.*?)'
+ #读取文件内容
+ 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'{strs}',content)
+ #重新写入进去
+ with open(rcbox_path, 'w') as f:
+ f.write(new_content)
+
#修改rcproj文件,删除没有模型的component,保留最多model 的component
def changeRcprojFile(pid):
# 解析XML文件
@@ -224,6 +245,12 @@ def uploadControlPointsOss(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()))):
os.makedirs(os.path.join(config.workdir,"screen", time.strftime("%y%m%d",time.localtime())))
diff --git a/libs/computerRecboxCenterByPoint.py b/libs/computerRecboxCenterByPoint.py
new file mode 100644
index 0000000..f0ce63b
--- /dev/null
+++ b/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
\ No newline at end of file
diff --git a/main_step2.py b/main_step2.py
index a1b758b..9da8c28 100644
--- a/main_step2.py
+++ b/main_step2.py
@@ -6,7 +6,7 @@ if platform.system() == 'Windows':
#sys.path.append('libs')
else:
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
def load_model(pid):
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'
else:
calulate_type = '-mvs'
-
-
+
+ #翻转相机的线向下
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")}" \
{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)
diff --git a/timer/get_task_to_db.py b/timer/get_task_to_db.py
index 703d181..0d07d7a 100644
--- a/timer/get_task_to_db.py
+++ b/timer/get_task_to_db.py
@@ -43,7 +43,10 @@ def readTask(key):
print("走新的建模系统不是分布式插入-重建工单",key,pid,psid)
libs_db.add_task(taskData)
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)
if int(psid) == 41 or int(psid) == 85:
taskData["priority"] = 0
diff --git a/timer/setup_oem_exe.py b/timer/setup_oem_exe.py
new file mode 100644
index 0000000..47da24b
--- /dev/null
+++ b/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()
\ No newline at end of file
diff --git a/tools/auto_distance.py b/tools/auto_distance.py
index 393e813..57fc748 100644
--- a/tools/auto_distance.py
+++ b/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]
time.sleep(3)
#截屏
- if pid != "":
+ if pid.isdigit():
common.saveScreenImg(pid)
time.sleep(3)
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
@@ -59,6 +66,53 @@ def find_and_maximize_window(window_title):
# ag.typewrite(distance)
# 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):
psid = libs.getPSid(pid)
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)
def main():
-
+ # time.sleep(6)
+ # exportPointColud()
+ # exit()
while True:
time.sleep(1)
title = "wait"