后期地图处理:去噪

建图时,由于算法、激光雷达等缺陷,在实际上本应不可进入区域会变成可进入。这种区域多了,会增加后面导航难度。

图1 去噪前的占据栅格图

对图1这张占据栅格图。标号1处放的是一张床,可建图时让出现了部分可进入,这会使得规划全局路径时选择从它这里过了。

去噪就是要让标号1这种区域,变得不可进入。图11是去噪后结果。去噪方法核心:从初始点开始(图1中的M),随着机器人移动会生成连通区,只要找到包围这个连通区轮廓,这个轮廓外的非占据像栅格就可能是噪声。

 

一、二值图:gray.png

图2 gray.png

NO_INFORMATION或<60的栅格值置为0,否则255。

 

二、二值图:gray-lt60.png

图3 gray-lt60.png

<60的栅格值置为0,否则255。相比于gray.png,NO_INFORMATION保留原值,也是255。

gray-lt60.png将在最后一步时使用,下一步骤是基于gray.png。

 

三、以radius=1(3x3核)第一次膨胀

图4 gray-dilate-1st.png

连通靠得近的栅格,减少轮廓数。radius不能太大,否则像图1中的“标号2”,会被错误连通。

opencv中膨胀和腐蚀不是可逆的。举个例子,对mat-A,首先raidus=3膨胀后,然后radius=2腐蚀,得到mat-B,可能不等于mat-A以raiuds=1膨胀后的结果。为什么不一样,参考图1的标号2部分。

 

四、找到第一次膨胀后的所有轮廓,对于各轮廓占据栅格,值置为该轮廓index加1

图5 contours-1nd-all.png

 

  1. cv::findContours,找到所有轮廓。
  2. cv::drawContours,画上一个cv::Mat
  3. 使用一个和cv::Mat“相等”的width*height字节内存块,当对应栅格是轮廓点时,字节值设置为该轮廓的index加1,否则是0。假设变量aux_map_data指向这内存块。

 

五、在第一次膨胀基础上,以radius=2第二次膨胀

图6 gray-dilate-3nd.png

相当于给原图来了次radius=3的膨胀,这会让更多轮廓连通起来。

 

六、生成主轮廓

图7 contours-2nd-master.png

对那个有着最多点的轮廓,称为主轮廓。

 

七、根据主轮廓,找到它覆盖了radius=1哪些轮廓,由这些轮廓画出一个“主轮廓”

图8 denoise-master.png

生成的这个“主轮廓”有两个特点。1)是radius=3主轮廓的子集。2)radius=1时是0、radius=3是255的栅格,值是0,不该连的不连。

这个“主轮廓”已不符合opencv轮廓定义,但为叙述方便,把双引号省了。

 

九、填充主轮廓

图10 denoise-filled-inter.png

中间灰白部分是要填充的栅格。灰白只是为注释,这些栅格的最后值是255(白色)。

以原点为起点,针对该左、右、上、下,四个方向扩散。如果扩散出的点在轮廓内,以它继续扩散。如何判断是在轮廓内?——横向两端有轮廓的点,或纵向两端有轮廓的点。

 

十、找出噪声

图11 去噪后地图

结合denoise-filled-inter.png、gray-lt60.png,对gray-lt60.png不是255的栅格,如果在denoise-filled-inter.png是0,即不在主轮廓,那就标记为噪声。

全部评论: 0

    写评论: