图片/CAD 图纸方案
墙线识别
import cv2
import numpy as np
img = cv2.imread("floorplan.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 边缘检测
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
# 霍夫直线检测
lines = cv2.HoughLinesP(
edges,
rho=1,
theta=np.pi / 180,
threshold=100,
minLineLength=50,
maxLineGap=10
)
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
minLineLength 控制最短检测长度,maxLineGap 控制允许的断线间距。
圆柱识别
circles = cv2.HoughCircles(
gray,
cv2.HOUGH_GRADIENT,
dp=1,
minDist=20,
param1=50,
param2=30,
minRadius=10,
maxRadius=100
)
if circles is not None:
circles = np.uint16(circles[0])
for cx, cy, r in circles:
cv2.circle(img, (cx, cy), r, (255, 0, 0), 2)
方柱/立柱识别
通过轮廓检测找矩形区域:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
area = cv2.contourArea(cnt)
if area < 200:
continue
# 多边形逼近
epsilon = 0.02 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
# 4 个顶点且面积合理 → 矩形 → 立柱
if len(approx) == 4:
x, y, w, h = cv2.boundingRect(approx)
aspect = w / h if h > 0 else 0
if 0.5 < aspect < 2.0: # 长宽比合理
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
3D 点云方案(激光雷达/深度图)
墙面提取(RANSAC 平面分割)
import open3d as o3d
pcd = o3d.io.read_point_cloud("scan.ply")
# RANSAC 平面分割
plane_model, inliers = pcd.segment_plane(
distance_threshold=0.01,
ransac_n=3,
num_iterations=1000
)
wall_cloud = pcd.select_by_index(inliers)
other_cloud = pcd.select_by_index(inliers, invert=True)
重复调用提取多个平面(多面墙体)。
圆柱提取(PCL RANSAC)
PCL 提供 SACMODEL_CYLINDER 直接拟合圆柱:
pcl::SACSegmentationFromNormals<PointT, NormalT> seg;
seg.setModelType(pcl::SACMODEL_CYLINDER);
seg.setMethodType(pcl::SAC_RANSAC);
seg.setDistanceThreshold(0.05);
seg.segment(*inliers, *coefficients);
Python 可通过 python-pcl 或 Open3D 的 cylinder_fit 实现。
实时摄像头方案(推荐)
传统几何算法在以下情况容易失效:
- 图纸断线、噪声
- 光照变化
- 非标准图纸格式
推荐直接用 YOLO 检测/分割模型:
from ultralytics import YOLO
model = YOLO("yolov8n-seg.pt")
# 训练自定义数据集(wall / pillar / cylinder 三类)
model.train(data="floorplan.yaml", epochs=100, imgsz=640)
# 推理
results = model("room.jpg")
results[0].show()
YOLOv8-seg 直接输出分割 Mask,比 HoughLines 对真实环境更鲁棒。
方案选型建议
| 场景 | 推荐方案 |
|---|---|
| 标准黑白 CAD 图 | Canny + HoughLinesP |
| 平面图圆柱 | HoughCircles |
| 复杂/真实户型图 | 轮廓检测 + 面积过滤 |
| 激光雷达点云 | RANSAC 平面/圆柱拟合 |
| 实时摄像头 | YOLOv8-seg 训练定制模型 |
实际项目中通常是”深度学习检测 + 几何后处理”组合使用,单纯依赖传统算法稳定性较差。
