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"