You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于OpenCV的LiDAR地图图像直线规整化处理技术问询

LiDAR地图规整化处理问题

图像说明

  • 初次处理后的LiDAR地图:
    初次处理后的LiDAR地图
    该图像是LiDAR传感器生成的地图经初次处理后的结果,存在大量凹凸不平区域,边缘并非标准直线。

  • 目标规整样式:
    目标规整样式
    希望将处理结果调整为该图像所示的规整样式。

  • LiDAR原始地图:
    LiDAR原始地图
    这是LiDAR扫描得到的原始地图图像。

问题描述

尝试使用Hough Line(霍夫直线)算法处理,但效果不理想,希望找到一种可适配多种场景的通用处理方法。

现有处理代码

import numpy as np
import math
import cv2

def get_dist(pt1, pt2):
    return math.hypot(pt1[0]-pt2[0], pt1[1]-pt2[1])
def reorderPts(pts):
    idx = np.lexsort((pts[:, 1], pts[:, 0]))
    pts = pts[idx]

    if pts[0, 1] > pts[1, 1]:
        pts[[0, 1]] = pts[[1, 0]]

    if pts[2, 1] < pts[3, 1]:
        pts[[2, 3]] = pts[[3, 2]]

    return pts

def solve(src):
    H, W = src.shape[:2]
    dst = src.copy()

    gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
    _, bin = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
    bin = cv2.erode(bin, np.ones((5, 5)))

    cv2.floodFill(bin, np.zeros((H+2, W+2), np.uint8), (0, 0), 0)
    bin = cv2.medianBlur(bin, 7)

    nonRectArea = bin.copy()
    cv2.floodFill(nonRectArea, np.zeros((H+2, W+2), np.uint8), (W//2, H//2), 0)
    bin[np.where(nonRectArea == 255)] = 0

    contours, _ = cv2.findContours(bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    rect = cv2.minAreaRect(contours[0])
    box = cv2.boxPoints(rect)
    box = np.int0(box)
    cv2.drawContours(dst, [box], 0, (0, 255, 0), 1)

    srcQuad = reorderPts(box.reshape(4, 2).astype(np.float32))
    dw = int(get_dist(srcQuad[0], srcQuad[3])*2)
    dh = int(get_dist(srcQuad[0], srcQuad[1])*2)
    dstQuad = np.array([[0, 0], [0, dh], [dw, dh], [dw, 0]], np.float32)
    pers = cv2.getPerspectiveTransform(srcQuad, dstQuad)
    dst = cv2.warpPerspective(src, pers, (dw, dh))

    gray = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
    _, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
    thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, np.ones((25, 25)))

    lines = cv2.HoughLinesP(thresh, 0.8, np.pi/180, 80, minLineLength=30, maxLineGap=100)
    w, h = dst.shape[:2]
    mask = np.zeros((w, h), dtype=np.uint8)
    for line in lines:
        x1, y1, x2, y2 = line[0]
        cv2.line(dst, (x1,y1), (x2, y2), (0,255,0), 3)
        cv2.line(mask, (x1,y1), (x2, y2), 255, 3)

    mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, np.ones((7, 7), dtype=np.uint8))
    thresh = cv2.bitwise_and(thresh,thresh,mask=~mask)
    thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, np.ones((9, 9), dtype=np.uint8))

    cv2.imshow("src", src)
    cv2.imshow("dst", dst)
    cv2.imshow("thresh", thresh)
    cv2.waitKey()

src = cv2.imread('map.png')
solve(src)

代码运行结果

  • 结果图1:
    代码运行结果1
  • 结果图2:
    代码运行结果2

解决方案建议

针对LiDAR地图的规整化需求,推荐以下几种通用处理思路:

  1. 轮廓多边形逼近
    用cv2.approxPolyDP对提取的轮廓做多边形逼近,设置合适的精度(epsilon值取轮廓周长的0.01~0.05倍),直接将不规则轮廓拟合为四边形。之后通过透视变换把拟合区域映射成标准矩形。
    示例片段:

    contours, _ = cv2.findContours(bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnt = contours[0]
    epsilon = 0.02 * cv2.arcLength(cnt, True)
    approx = cv2.approxPolyDP(cnt, epsilon, True)
    if len(approx) == 4:
        # 后续透视变换处理逻辑
    
  2. 形态学优化+直线拟合
    在现有形态学处理基础上,先用大尺寸闭运算填充凹凸区域,提取边缘后用RANSAC直线拟合工具获取规整边缘直线,最后根据拟合直线生成标准地图。

  3. 栅格地图区域规整
    将LiDAR地图转为栅格地图,通过连通区域分析识别可通行区域,再对该区域做最小矩形包围,或用膨胀-腐蚀操作把不规则边缘平滑为直线,最终生成规整栅格地图。

这些方法先去除噪声和凹凸干扰,再通过几何拟合或形态学操作实现规整化,比单纯霍夫直线检测鲁棒性更强,适配更多LiDAR场景。


内容的提问来源于stack exchange,提问作者MobileRobotics

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 12:38:11