理解np.expand_dims()和np.delete()

本文深入探讨了NumPy中扩展维度和删除特定轴元素的方法,通过实例解释了expand_dims和delete函数的应用,帮助读者理解如何在数据处理中有效操作数组的形状。

主要是为了记在博客上让自己不忘掉,倒是没有什么技术含量。

这个函数顾名思义就是扩展维度的。参考博客讲的很详细了,这里附上我的小实验:

https://blog.youkuaiyun.com/qq_16949707/article/details/53418912

expand_dims(a, axis)就是在axis的那一个轴上把数据加上去,这个数据在axis这个轴的0位置。 
例如原本为一维的2个数据,axis=0,则shape变为(1,2),axis=1则shape变为(2,1) 
再例如 原本为 (2,3),axis=0,则shape变为(1,2,3),axis=1则shape变为(2,1,3)

>>X=np.float32(12,32,34)
>>print X
[12. 32. 34.]
>>print X[...,-1]
34.0
>>P=np.expand_dims(X[...,-1],axis=1)
>>print P
[34.] 

https://blog.youkuaiyun.com/zxyhhjs2017/article/details/80157930

numpy.delete(arr,obj,axis=None) 
arr:输入向量 
obj:表明哪一个子向量应该被移除。可以为整数或一个int型的向量 
axis:表明删除哪个轴的子向量,若默认,则返回一个被拉平的向量

>>X=np.delete(X,-1,axis=0)
>>print X
[12. 32.]

 

这个代码是直接对戴口罩未戴口罩进行识别,没有用到目标检测吗 """fasterRCNN对象创建""" import numpy as np import colorsys import os from keras import backend as K from keras.applications.imagenet_utils import preprocess_input from PIL import Image, ImageFont, ImageDraw import copy import math from net import fasterrcnn as frcnn from net import netconfig as netconfig from net import RPN as RPN from net import tools as tools class FasterRCNN(object): _defaults = { "model_path": './model_data/logs/epoch015-loss1.729-rpn1.025-roi0.704.h5', "classes_path": './model_data/index.txt', "confidence": 0.7, } @classmethod def get_defaults(cls, n): if n in cls._defaults: return cls._defaults[n] else: return "Unrecognized attribute name '" + n + "'" def __init__(self, **kwargs): """初始化faster RCNN""" self.__dict__.update(self._defaults) self.class_names = self._get_class() self.sess = K.get_session() self.config = netconfig.Config() self.generate() self.bbox_util = tools.BBoxUtility() self.confidence = 0.7 self.classes_path='./model_data/index.txt' self.model_path='./model_data/logs/epoch015-loss1.729-rpn1.025-roi0.704.h5' def _get_class(self): """获得所有的分类""" classes_path = os.path.expanduser(self.classes_path) with open(classes_path) as f: class_names = f.readlines() class_names = [c.strip() for c in class_names] return class_names def generate(self): """获得所有的分类""" model_path = os.path.expanduser(self.model_path) assert model_path.endswith('.h5'), 'Keras model or weights must be a .h5 file.' # 计算总的种类 self.num_classes = len(self.class_names) + 1 # 载入模型,如果原来的模型里已经包括了模型结构则直接载入。 # 否则先构建模型再载入 self.model_rpn, self.model_classifier = frcnn.get_predict_model(self.config, self.num_classes) self.model_rpn.load_weights(self.model_path, by_name=True) self.model_classifier.load_weights(self.model_path, by_name=True, skip_mismatch=True) print('{} model, anchors, and classes loaded.'.format(model_path)) # 画框设置不同的颜色 hsv_tuples = [(x / len(self.class_names), 1., 1.) for x in range(len(self.class_names))] self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) self.colors = list( map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), self.colors)) def get_img_output_length(self, width, height): def get_output_length(input_length): # input_length += 6 filter_sizes = [7, 3, 1, 1] padding = [3, 1, 0, 0] stride = 2 for i in range(4): # input_length = (input_length - filter_size + stride) // stride input_length = (input_length + 2 * padding[i] - filter_sizes[i]) // stride + 1 return input_length return get_output_length(width), get_output_length(height) def detect_image(self, image): """检测图片""" image_shape = np.array(np.shape(image)[0:2]) old_width = image_shape[1] old_height = image_shape[0] # 保存原始图片 old_image = copy.deepcopy(image) # 把图片的最短边resize到600 width, height = tools.get_new_img_size(old_width, old_height) image = image.resize([width, height]) # 图片转成数组 photo = np.array(image, dtype=np.float64) # 图片预处理,归一化 photo = preprocess_input(np.expand_dims(photo, 0)) # 使用RPN预测,获得概率x_classx_regr preds = self.model_rpn.predict(photo) # 将预测结果进行解码 # 获得所有先验框 anchors = RPN.create_anchor(self.get_img_output_length(width, height), width, height) # 解码获得建议框,这里得到了300个建议框,注意其坐标均为0-1间 rpn_results = self.bbox_util.detection_out(preds, anchors, 1, confidence_threshold=0) # 将返回的0-1的建议框映射到共享特征图,如果特征图为38*38,值域变成0-38之间,R为300行4列,分别是左上角右下角坐标 R = rpn_results[0][:, 2:] R[:, 0] = np.array(np.round(R[:, 0] * width / self.config.rpn_stride), dtype=np.int32) R[:, 1] = np.array(np.round(R[:, 1] * height / self.config.rpn_stride), dtype=np.int32) R[:, 2] = np.array(np.round(R[:, 2] * width / self.config.rpn_stride), dtype=np.int32) R[:, 3] = np.array(np.round(R[:, 3] * height / self.config.rpn_stride), dtype=np.int32) print(R) # R转换一下,前两列是左上角坐标,后两列是宽高 R[:, 2] -= R[:, 0] R[:, 3] -= R[:, 1] base_layer = preds[2] delete_line = [] for i, r in enumerate(R): if r[2] < 1 or r[3] < 1: delete_line.append(i) R = np.delete(R, delete_line, axis=0) bboxes = [] probs = [] labels = [] # 分批次遍历建议框,每批32个 for jk in range(R.shape[0] // self.config.num_rois + 1): # 取出32个建议框 ROIs = np.expand_dims(R[self.config.num_rois * jk:self.config.num_rois * (jk + 1), :], axis=0) # 判断建议框是否有效 if ROIs.shape[1] == 0: break # 对最后一次整除不全,不能到32个的建议框小批进行填充 if jk == R.shape[0] // self.config.num_rois: # pad R curr_shape = ROIs.shape target_shape = (curr_shape[0], self.config.num_rois, curr_shape[2]) ROIs_padded = np.zeros(target_shape).astype(ROIs.dtype) ROIs_padded[:, :curr_shape[1], :] = ROIs ROIs_padded[0, curr_shape[1]:, :] = ROIs[0, 0, :] ROIs = ROIs_padded # 将共享特征层建议框传入end_classifier进行预测 # P_cls为(Batch_size,32个建议框,21) # P_regr为(Batch_size,32个建议框,80) [P_cls, P_regr] = self.model_classifier.predict([base_layer, ROIs]) # 判断输出的每批中每个建议框是否真实包含我们要的物体,本身置信度阈值设置为0.9,如果是背景也要跳过 for ii in range(P_cls.shape[1]): # P_cls[0, ii, :-1]是21个概率组成的列表 if np.max(P_cls[0, ii, :-1]) < self.confidence or np.argmax(P_cls[0, ii, :]) == (P_cls.shape[2] - 1): continue # 获得label label = np.argmax(P_cls[0, ii, :-1]) # 获得坐标信息 (x, y, w, h) = ROIs[0, ii, :] # 其实就是label cls_num = np.argmax(P_cls[0, ii, :-1]) # 获取框的信息,并改变数量级 (tx, ty, tw, th) = P_regr[0, ii, 4 * cls_num:4 * (cls_num + 1)] tx /= self.config.classifier_regr_std[0] ty /= self.config.classifier_regr_std[1] tw /= self.config.classifier_regr_std[2] th /= self.config.classifier_regr_std[3] # 获取到共享特征层上真实的坐标信息 cx = x + w / 2. cy = y + h / 2. cx1 = tx * w + cx cy1 = ty * h + cy w1 = math.exp(tw) * w h1 = math.exp(th) * h x1 = cx1 - w1 / 2. y1 = cy1 - h1 / 2. x2 = cx1 + w1 / 2 y2 = cy1 + h1 / 2 x1 = int(round(x1)) y1 = int(round(y1)) x2 = int(round(x2)) y2 = int(round(y2)) # bboxes是最终从300个建议框过滤出来与目标物体对应的建议框 # 但注意,这里的建议框还是存在重叠现象,因为之前仅仅靠物体置信度来筛选 bboxes.append([x1, y1, x2, y2]) probs.append(np.max(P_cls[0, ii, :-1])) labels.append(label) # 没检测到物体,返回 if len(bboxes) == 0: return old_image # 将38*38特征层的建议框映射到600*600 # 筛选出其中得分高于confidence的框,因此此时需要再次NMS删除重叠框 labels = np.array(labels) probs = np.array(probs) boxes = np.array(bboxes, dtype=np.float32) boxes[:, 0] = boxes[:, 0] * self.config.rpn_stride / width boxes[:, 1] = boxes[:, 1] * self.config.rpn_stride / height boxes[:, 2] = boxes[:, 2] * self.config.rpn_stride / width boxes[:, 3] = boxes[:, 3] * self.config.rpn_stride / height results = np.array( self.bbox_util.nms_for_out(np.array(labels), np.array(probs), np.array(boxes), self.num_classes - 1, 0.4)) top_label_indices = results[:, 0] top_conf = results[:, 1] boxes = results[:, 2:] #top_label_indices=labels #top_conf=probs # 大小调整到原图上,此时已经完成了建议框的计算 boxes[:, 0] = boxes[:, 0] * old_width boxes[:, 1] = boxes[:, 1] * old_height boxes[:, 2] = boxes[:, 2] * old_width boxes[:, 3] = boxes[:, 3] * old_height # simhei.ttf用于设置字体 font = ImageFont.truetype(font='model_data/simhei.ttf',size=np.floor(3e-2 * np.shape(image)[1] + 0.5).astype('int32')) thickness = (np.shape(old_image)[0] + np.shape(old_image)[1]) // old_width * 2 image = old_image for i, c in enumerate(top_label_indices): predicted_class = self.class_names[int(c)] score = top_conf[i] left, top, right, bottom = boxes[i] top = top - 5 left = left - 5 bottom = bottom + 5 right = right + 5 top = max(0, np.floor(top + 0.5).astype('int32')) left = max(0, np.floor(left + 0.5).astype('int32')) bottom = min(np.shape(image)[0], np.floor(bottom + 0.5).astype('int32')) right = min(np.shape(image)[1], np.floor(right + 0.5).astype('int32')) # 画框框 label = '{} {:.2f}'.format(predicted_class, score) draw = ImageDraw.Draw(image) label_size = draw.textsize(label, font) label = label.encode('utf-8') print(label) if top - label_size[1] >= 0: text_origin = np.array([left, top - label_size[1]]) else: text_origin = np.array([left, top + 1]) for i in range(thickness): draw.rectangle( [left + i, top + i, right - i, bottom - i], outline=self.colors[int(c)]) draw.rectangle( [tuple(text_origin), tuple(text_origin + label_size)], fill=self.colors[int(c)]) draw.text(text_origin, str(label, 'UTF-8'), fill=(0, 0, 0), font=font) del draw return image def close(self): self.sess.close()
最新发布
09-17
import tkinter as tk from tkinter import ttk, filedialog import open3d as o3d import numpy as np from scipy.optimize import least_squares class EnhancedShapeAnalyzer: def __init__(self): self.pcd = None self.raw_pcd = None self.transform = np.eye(4) self.results = {"type": "unknown", "confidence": 0.0} self.camera_params = { "focal_length": 500, # 像素单位 "sensor_width": 36, # 毫米 "max_offset": 0.2, # 最大中心偏移(米) "depth_base": 1000 # 基准深度(毫米) } def load_data(self, folder_path): """加载并预处理数据""" try: # 加载原始数据 self.raw_pcd = o3d.io.read_point_cloud(f"{folder_path}/scan.ply") transform_data = np.load(f"{folder_path}/transform.npz") self.transform = transform_data['matrix'] # 应用变换并中心化 self.pcd = self.raw_pcd.transform(np.linalg.inv(self.transform)) self._center_normalization() return True except Exception as e: print(f"数据加载失败: {str(e)}") return False def _center_normalization(self): """将点云中心对齐到坐标系原点""" points = np.asarray(self.pcd.points) current_center = np.mean(points, axis=0) self.pcd.translate(-current_center) print(f"中心化偏移量: {current_center}") def _perspective_correction(self, raw_size, depth): """透视尺寸校正""" depth_mm = depth * 1000 # 转换为毫米 scale_factor = self.camera_params["focal_length"] / \ (self.camera_params["focal_length"] + (depth_mm - self.camera_params["depth_base"]) / self.camera_params["sensor_width"]) return raw_size * scale_factor def analyze_shape(self): """执行形状分析流程""" if not self._preprocess(): return "预处理失败" self.results = {"type": "unknown", "confidence": 0.0} # 并行检测所有形状 candidates = [] if sphere_conf := self._detect_sphere(): candidates.append(("sphere", self.results.copy())) if cylinder_conf := self._detect_cylinder(): candidates.append(("cylinder", self.results.copy())) if cuboid_conf := self._detect_cuboid(): candidates.append(("cuboid", self.results.copy())) # 选择最佳结果 valid_candidates = [c for c in candidates if c[1]["confidence"] >= 0.5] if valid_candidates: best = max(valid_candidates, key=lambda x: x[1]["confidence"]) self.results = best[1] return best[0] return "unknown" def _preprocess(self): """数据预处理流程""" try: # 多阶段降采样 self.pcd = self.pcd.voxel_down_sample(0.005) self.pcd = self.pcd.voxel_down_sample(0.003) # 统计滤波 self.pcd, _ = self.pcd.remove_statistical_outlier(nb_neighbors=20, std_ratio=1.5) return True except Exception as e: print(f"预处理失败: {str(e)}") return False def _detect_sphere(self): """精密球体检测""" try: # 分割平面点云 _, inliers = self.pcd.segment_plane(0.01, 3, 1000) sphere_pcd = self.pcd.select_by_index(inliers, invert=True) points = np.asarray(sphere_pcd.points) if len(points) < 100: return 0.0 # 最小二乘优化 def sphere_loss(params): cx, cy, cz, r = params return np.linalg.norm(points - [cx, cy, cz], axis=1) - r init_center = np.mean(points, axis=0) init_radius = np.mean(np.linalg.norm(points - init_center, axis=1)) opt = least_squares(sphere_loss, [*init_center, init_radius], loss='soft_l1') # 中心验证 if not self._validate_center(opt.x[:3]): print("球体中心超出允许范围") return 0.0 # 透视校正 corrected_radius = self._perspective_correction(opt.x[3], opt.x[2]) # 置信度计算 residuals = sphere_loss(opt.x) inlier_ratio = np.sum(np.abs(residuals) < 0.02) / len(residuals) center_score = 1 - np.linalg.norm(opt.x[:3]) / self.camera_params["max_offset"] confidence = 0.6 * inlier_ratio + 0.4 * center_score if confidence > self.results["confidence"]: self.results = { "type": "sphere", "radius": float(corrected_radius), "center": opt.x[:3].tolist(), "confidence": float(confidence), "_points": points } return confidence except Exception as e: print(f"球体检测异常: {str(e)}") return 0.0 def _detect_cylinder(self): """精密圆柱检测""" try: # 分割平面点云 _, inliers = self.pcd.segment_plane(0.01, 3, 1000) cyl_pcd = self.pcd.select_by_index(inliers, invert=True) points = np.asarray(cyl_pcd.points) if len(points) < 100: return 0.0 # PCA分析主方向 cov = np.cov(points.T) _, vecs = np.linalg.eigh(cov) axis = vecs[:, 2] # 非线性优化 def cylinder_loss(params): a, b, c, x0, y0, z0, r = params dir_vec = np.array([a, b, c]) dir_vec /= np.linalg.norm(dir_vec) + 1e-8 pts_vec = points - [x0, y0, z0] cross = np.cross(pts_vec, dir_vec) return np.linalg.norm(cross, axis=1) - r init_center = np.mean(points, axis=0) opt = least_squares(cylinder_loss, [*axis, *init_center, 0.1], loss='soft_l1') # 参数提取 axis = opt.x[:3] / (np.linalg.norm(opt.x[:3]) + 1e-8) proj = np.dot(points - opt.x[3:6], axis) height = np.ptp(proj) center = opt.x[3:6] + axis * (np.min(proj) + height / 2) # 中心验证 if not self._validate_center(center): print("圆柱中心超出允许范围") return 0.0 # 透视校正 corrected_radius = self._perspective_correction(opt.x[6], center[2]) corrected_height = self._perspective_correction(height, center[2]) # 置信度计算 residuals = cylinder_loss(opt.x) inlier_ratio = np.sum(np.abs(residuals) < 0.015) / len(residuals) center_score = 1 - np.linalg.norm(center) / self.camera_params["max_offset"] confidence = 0.5 * inlier_ratio + 0.3 * center_score + 0.2 * (corrected_height / (2 * corrected_radius)) if confidence > self.results["confidence"]: self.results = { "type": "cylinder", "radius": float(corrected_radius), "height": float(corrected_height), "axis": axis.tolist(), "center": center.tolist(), "confidence": float(confidence), "_points": points } return confidence except Exception as e: print(f"圆柱检测异常: {str(e)}") return 0.0 def _detect_cuboid(self): """精密长方体检测""" try: # 多平面检测 planes = [] residual_pcd = self.pcd for _ in range(3): plane, inliers = residual_pcd.segment_plane(0.02, 3, 2000) if len(inliers) < 500: break planes.append(plane[:3]) residual_pcd = residual_pcd.select_by_index(inliers, invert=True) if len(planes) < 3: return 0.0 # 正交化处理 u, v, w = self._gram_schmidt(planes[0], planes[1], planes[2]) points = np.asarray(self.pcd.points) # 计算几何参数 proj_u = np.dot(points, u) proj_v = np.dot(points, v) proj_w = np.dot(points, w) dims = [np.ptp(proj_u), np.ptp(proj_v), np.ptp(proj_w)] center_3d = np.dot([np.mean(proj_u), np.mean(proj_v), np.mean(proj_w)], [u, v, w]) # 中心验证 if not self._validate_center(center_3d): print("长方体中心超出允许范围") return 0.0 # 透视校正 corrected_dims = [self._perspective_correction(d, center_3d[2]) for d in dims] # 置信度计算 ortho_score = 1 - (abs(np.dot(u, v)) + abs(np.dot(u, w)) + abs(np.dot(v, w))) / 3 center_score = 1 - np.linalg.norm(center_3d) / self.camera_params["max_offset"] confidence = 0.6 * ortho_score + 0.4 * center_score if confidence > self.results["confidence"]: self.results = { "type": "cuboid", "dimensions": corrected_dims, "center": center_3d.tolist(), "confidence": float(confidence), "_planes": planes } return confidence except Exception as e: print(f"长方体检测异常: {str(e)}") return 0.0 def _validate_center(self, center): """验证中心位置有效性""" return np.linalg.norm(center) < self.camera_params["max_offset"] def _gram_schmidt(self, u, v, w): """Gram-Schmidt正交化""" u = u / (np.linalg.norm(u) + 1e-8) v = v - np.dot(v, u) * u v = v / (np.linalg.norm(v) + 1e-8) w = w - np.dot(w, u) * u - np.dot(w, v) * v w = w / (np.linalg.norm(w) + 1e-8) return u, v, w class AnalysisGUI(tk.Tk): def __init__(self): super().__init__() self.title("三维精密分析系统 v4.0") self.geometry("1280x960") self.analyzer = EnhancedShapeAnalyzer() self._init_ui() def _init_ui(self): main_frame = ttk.Frame(self) main_frame.pack(fill="both", expand=True, padx=20, pady=20) # 文件选择区 file_frame = ttk.LabelFrame(main_frame, text="数据加载") file_frame.pack(fill="x", pady=10) self.path_entry = ttk.Entry(file_frame, width=80) self.path_entry.pack(side="left", expand=True, padx=5) ttk.Button(file_frame, text="浏览...", command=self._browse).pack(side="left") # 控制区 ctrl_frame = ttk.Frame(main_frame) ctrl_frame.pack(fill="x", pady=10) ttk.Button(ctrl_frame, text="开始分析", command=self._analyze).pack(side="left", padx=5) ttk.Button(ctrl_frame, text="原始点云", command=lambda: self._show_pcd(self.analyzer.raw_pcd)).pack(side="left") ttk.Button(ctrl_frame, text="处理点云", command=lambda: self._show_pcd(self.analyzer.pcd)).pack(side="left") ttk.Button(ctrl_frame, text="显示结果", command=self._show_result).pack(side="left") # 结果显示区 result_frame = ttk.LabelFrame(main_frame, text="分析结果") result_frame.pack(fill="both", expand=True) self.result_text = tk.Text(result_frame, wrap="word", font=("Consolas", 12)) scrollbar = ttk.Scrollbar(result_frame, orient="vertical", command=self.result_text.yview) self.result_text.configure(yscrollcommand=scrollbar.set) scrollbar.pack(side="right", fill="y") self.result_text.pack(fill="both", expand=True, padx=10, pady=10) # 状态栏 self.status = ttk.Label(main_frame, relief="sunken") self.status.pack(fill="x", pady=5) def _browse(self): path = filedialog.askdirectory() if path: self.path_entry.delete(0, tk.END) self.path_entry.insert(0, path) def _analyze(self): self.status.config(text="分析中...") self.result_text.config(state="normal") self.result_text.delete(1.0, tk.END) if not self.analyzer.load_data(self.path_entry.get()): self._update_result("数据加载失败") return shape_type = self.analyzer.analyze_shape() res = self.analyzer.results output = [ "=== 三维精密分析结果 ===", f"识别类型: {shape_type.upper()}", f"综合置信度: {res.get('confidence', 0):.1%}", f"中心坐标: {np.round(res.get('center', [0, 0, 0]), 3).tolist()}" ] if shape_type == "sphere": output.extend([ f"\n球体半径: {res['radius']:.3f} 米", f"表面点数: {len(res.get('_points', []))}" ]) elif shape_type == "cylinder": output.extend([ f"\n圆柱半径: {res['radius']:.3f} 米", f"圆柱高度: {res['height']:.3f} 米", f"轴向向量: {np.round(res.get('axis', [0, 0, 0]), 3).tolist()}" ]) elif shape_type == "cuboid": output.extend([ "\n长方体尺寸:", f"X: {res['dimensions'][0]:.3f} 米", f"Y: {res['dimensions'][1]:.3f} 米", f"Z: {res['dimensions'][2]:.3f} 米" ]) self.result_text.insert(tk.END, "\n".join(output)) self.result_text.config(state="disabled") self.status.config(text=f"分析完成 - 置信度: {res.get('confidence', 0):.1%}") def _show_pcd(self, pcd): """显示点云可视化""" try: if pcd.is_empty(): return vis = o3d.visualization.Visualizer() vis.create_window(window_name="点云视图", width=800, height=600) # 克隆点云以避免修改原始数据 cloned_pcd = o3d.geometry.PointCloud(pcd) cloned_pcd.paint_uniform_color([0.6, 0.6, 0.6]) vis.add_geometry(cloned_pcd) self._add_center_marker(vis) vis.run() vis.destroy_window() except Exception as e: print(f"可视化错误: {str(e)}") def _show_result(self): """显示分析结果的可视化""" try: res = self.analyzer.results if res["confidence"] < 0.5: self._update_result("无有效分析结果") return vis = o3d.visualization.Visualizer() vis.create_window(window_name="三维分析结果", width=1000, height=800) # 显示处理后的点云 base_pcd = self.analyzer.pcd.paint_uniform_color([0.8, 0.8, 0.8]) vis.add_geometry(base_pcd) # 显示检测结果 if res["type"] == "sphere": self._show_sphere_result(vis, res) elif res["type"] == "cylinder": self._show_cylinder_result(vis, res) elif res["type"] == "cuboid": self._show_cuboid_result(vis, res) # 添加中心标记坐标系 self._add_center_marker(vis) coord_frame = o3d.geometry.TriangleMesh.create_coordinate_frame(size=0.5) vis.add_geometry(coord_frame) vis.run() vis.destroy_window() except Exception as e: print(f"结果可视化失败: {str(e)}") def _show_sphere_result(self, vis, res): """显示球体检测结果""" sphere = o3d.geometry.TriangleMesh.create_sphere(res["radius"]) sphere.translate(res["center"]) sphere.paint_uniform_color([1, 0, 0]) vis.add_geometry(sphere) # 显示特征点 inlier_pcd = o3d.geometry.PointCloud() inlier_pcd.points = o3d.utility.Vector3dVector(res["_points"]) inlier_pcd.paint_uniform_color([1, 0.5, 0]) vis.add_geometry(inlier_pcd) def _show_cylinder_result(self, vis, res): """显示圆柱检测结果""" cylinder = o3d.geometry.TriangleMesh.create_cylinder( radius=res["radius"], height=res["height"] ) # 计算旋转矩阵 axis = np.array(res["axis"]) z_axis = np.array([0, 0, 1]) rotation = self._get_rotation_matrix(axis, z_axis) cylinder.rotate(rotation) # 调整位置到底面中心 cylinder.translate(np.array(res["center"]) - axis * res["height"] / 2) cylinder.paint_uniform_color([0, 0.8, 0]) vis.add_geometry(cylinder) def _show_cuboid_result(self, vis, res): """显示长方体检测结果""" obb = o3d.geometry.OrientedBoundingBox.create_from_points( o3d.utility.Vector3dVector(np.asarray(self.analyzer.pcd.points)) ) obb.color = [0, 0, 1] vis.add_geometry(obb) def _add_center_marker(self, vis): """添加中心标记""" center_sphere = o3d.geometry.TriangleMesh.create_sphere(radius=0.03) center_sphere.paint_uniform_color([1, 1, 0]) # 黄色 vis.add_geometry(center_sphere) def _get_rotation_matrix(self, from_vec, to_vec): """计算两个向量间的旋转矩阵""" from_vec = from_vec / np.linalg.norm(from_vec) to_vec = to_vec / np.linalg.norm(to_vec) v = np.cross(from_vec, to_vec) c = np.dot(from_vec, to_vec) kmat = np.array([[0, -v[2], v[1]], [v[2], 0, -v[0]], [-v[1], v[0], 0]]) return np.eye(3) + kmat + kmat.dot(kmat) * (1 / (1 + c)) def _update_result(self, msg): """更新结果显示""" self.result_text.config(state="normal") self.result_text.delete(1.0, tk.END) self.result_text.insert(tk.END, msg) self.result_text.config(state="disabled") self.status.config(text="操作完成") if __name__ == "__main__": app = AnalysisGUI() app.mainloop() 在运行时代码总是把一整个场景都识别进去判断了,如果把墙体平面去掉,只留下物体的点云会不会有效果呢,请基于这个思想修改代码,并给出完整的代码
05-12
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

keneyr

老爷~给小的赏点盘缠吧555~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值