OpenCV 识别户型图中的墙线与柱子:HoughLines、轮廓检测与 YOLO

图片/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 训练定制模型

实际项目中通常是”深度学习检测 + 几何后处理”组合使用,单纯依赖传统算法稳定性较差。