“悉灵杯”课题研究-RGB_D相机SDK集成及Open3d点云基本处理
本文介通过借助RGB_D相机SDK,基于Pycharm平台,使用open3d进行简单的点云处理。

一. 环境及硬件介绍


1. Visual Studio 2022

2. OpenCV 4.6.0

3. Open3D 0.15.1

4. Python 3.9

5. 悉灵相机MV-EB435i,SDK版本Mv3dRgbd_V1.0.0_Win


二. 点云数据结构及获取


      参考SDK中给出的结构体参数,分析图像格式,以此提取图像。

     

      在ImageData数组中,储存了每帧图像数据所包含的nImageCount个图像。每一副图像的数据由pdata 储存。在定义了结构体stPointCloudImage中,我们所需要的点云数据信息就存储在pdata指针所指向的地址。

      RGB_D相机没有直接输出点云数据,而是先输出了深度图像数据。同时,SDK中提供的MV3D_RGBD_MapDepthToPointCloud函数帮助将深度图像转换为点云图像。考虑到本课题将在PyCharm平台进行后续点云处理,于是选择将一帧点云文件单独写入一个.xyz格式的文件,从而生成xyz格式的点云文件,以供其他平台灵活使用。

C++代码

//打开存储文件
    std::ofstream os;
    std::string path = "D:\\Desktop\\pointscatch\\";
    int flagnum = 0;
    bool exit_flag = TRUE;

    MV3D_RGBD_FRAME_DATA stFrameData = { 0 };
    while (exit_flag)
    {
        // 获取图像数据
        int nRet = MV3D_RGBD_FetchFrame(handle, &stFrameData, 5000);
        //获取图像帧
        if (MV3D_RGBD_OK == nRet)
        {
            //图像帧很多类型,当类型为深度时将其转换为点云
            for (int i = 0; i < stFrameData.nImageCount; i++)
            {
                //若是深度格式则开始转换
                if (ImageType_Depth == stFrameData.stImageData[i].enImageType)
                {
                    path = "D:\\Desktop\\pointscatch\\" + std::to_string(flagnum) + ".xyz";
                    os.open(path, std::ios::app);
                    flagnum++;
                    MV3D_RGBD_IMAGE_DATA stPointCloudImage;
                    //将当前帧转换为点云
                    nRet = MV3D_RGBD_MapDepthToPointCloud(handle, &stFrameData.stImageData[i], &stPointCloudImage);
                    //pPtr 指向 点云存储起始地址
                    float* pPtr = (float*)stPointCloudImage.pData;
                    int nPointNum = stPointCloudImage.nDataLen / (sizeof(float) * 3);

                    //从第一个点云开始向文件流中写入 xyz 坐标
                    LOGD("Start write Points of %d framenum!", stPointCloudImage.nFrameNum);
                    for (int nPntIndex = 0; nPntIndex < nPointNum; ++nPntIndex)
                    {
                        if (pPtr[nPntIndex * 3 + 0] != 0 || pPtr[nPntIndex * 3 + 1] != 0 || pPtr[nPntIndex * 3 + 2] != 0)
                            os << pPtr[nPntIndex * 3 + 0] << ' ' << pPtr[nPntIndex * 3 + 1] << ' ' << pPtr[nPntIndex * 3 + 2] << std::endl;
                    }
                    LOGD("_MapDepthToPointCloud() Run Succeed: framenum (%d) height(%d) width(%d)  len (%d)!", stPointCloudImage.nFrameNum,
                        stPointCloudImage.nHeight, stPointCloudImage.nWidth, stPointCloudImage.nDataLen);
                    os.close();
                }

                //若获取图像帧失败则退出
                if (MV3D_RGBD_OK != nRet)
                {
                    break;
                }
            }
        }
        //按键退出
        if (_kbhit())
        {
            exit_flag = FALSE;
        }
    }



三. 点云数据处理

1、点云可视化

      确定了点云文件保存路径后,对保存下的.xyz格式的点云文件,在Pycharm平台,直接使用open3d库中函数read_point_cloud和visualization.draw_geometries进行简单的读取和显示。

 (以下及后续代码为python)    

pcd = o3d.io.read_point_cloud('pointscloud.xyz',format='xyz')
o3d.visualization.draw_geometries([pcd],"Open3D pointscloud", width=800, height=600, left=50, top=50,
                                  point_show_normal=False, mesh_show_wireframe=False,
                                  mesh_show_back_face=False)

2、Raw深度图可视化

      由官方提供的demo获取的深度图原始文件。分析了文件存储格式后,将raw文件数据转写成可视化的png文件,图片大小为1280*720。



3、点云去噪

      直接读取采集后的点云图像并可视化,会发现存在大量的放射状噪点,采用统计滤波的方法,对点云图像去噪。对于大量采集到的点云文件,进行批量处理,便于从中筛选清晰合适的点云图像做后续处理




4、法向量估计

      法向量是点云的一个非常重要的属性。目前很多点云算法的实现,例如点云分割,表面重建等等,都要基于精确的法向量估计。法线估计的实质上就是对于点云空间中的每一个点,在其邻域内估计出一个平面。估计一个平面需要一个点和一个法向量,这个法向量就是我们所要估计的法向量。这个点就是这一群邻域点(与该点自身)的平均值。由空间变换可知,点云中每一点的法向量夹角及曲率值均不随物体的运动而改变,具有刚体运动不变性。

      点云法向量求解需要其邻域内点支持,而邻域的大小一般由邻域半径值或临近点个数来表示。现实中需要根据点分别率、物体细节精细程度和用途等因素来取值。过大的邻域会抹平三维结构细节使得法向量过于粗糙,而过小的邻域由于包含了太少的点受噪声干扰程度较强。

      先对滤波后的点云进行下采样处理,再进行法线估计,这里使用了open3d库中的KDTreeSearchParamHybrid计算法线并可视化。

print("计算下采样点云的法线")
downpcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.1, max_nn=30))  # 设置搜索半径0.1m,邻域内30个点
o3d.visualization.draw_geometries([downpcd], "Open3D normal estimation",
                                  width=800, height=600, left=50, top=50,
                                  point_show_normal=True,
                                  mesh_show_wireframe=False,
                                  mesh_show_back_face=False)


5、包围框计算

      本课题采用了两种包围框方法,分别是AABB包围盒和OBB包围盒。两种包围方式尤其各自的特性。AABB包围盒是与坐标轴对齐的包围盒,每一面都与空间坐标轴平行,构造简单, 包围的紧密性较差;OBB为有向包围框,本质上是最贴近物体形状的长方体,所以其紧密性更好。

       如下图所示,红色为AABB包围框,绿色为OBB包围框。

# AABB包围盒
aabb = pcd.get_axis_aligned_bounding_box()
aabb.color = (1, 0, 0)
# OBB包围盒
obb = pcd.get_oriented_bounding_box()
obb.color = (0, 1, 0)
o3d.visualization.draw_geometries([pcd, aabb, obb], window_name="点云包围盒",
                                  width=800, height=600,
                                  left=50, top=50,
                                  point_show_normal=False,
                                  mesh_show_wireframe=False,
                                  mesh_show_back_face=False)# 可视化




        代码链接: https://github.com/Sumu27/HaikangXiling



版权声明:本文为V社区用户原创内容,转载时必须标注文章的来源(V社区),文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:v-club@hikrobotics.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
上一篇

悉灵杯”课题研究-MV-EB435i立体相机基于opencv图像处理使用yolov5的物体识别

下一篇

OpenCV中利用knn进行数字(0-9)识别--RGB-D相机采集

评论请先登录 登录
全部评论 6
棒棒棒
2022-08-23 08:26:34
回复
好棒!
2022-08-23 07:47:45
回复
不错不错
2022-08-23 07:09:09
回复
好棒好棒非常棒
2022-08-23 07:08:51
回复
非常好
2022-08-23 06:36:50
回复
很好很好
2022-08-23 06:36:32
回复
  • 1
Lv.0
1
创作
2
粉丝
9
获赞
相关阅读
  • 海康机器人“悉灵杯”课题研究活动-获奖公布
    2022-09-05
  • 汽车行业-汽车焊点检测案例
    2022-09-01
  • VM3D模块学习经验分享
    2022-09-22
  • SC系列智能相机图像存储的几种方式
    2022-09-08
  • 有关条码二维码相关知识
    2022-08-30

请升级浏览器版本

您正在使用的浏览器版本过低,请升级最新版本以获得更好的体验。

推荐使用以下浏览器