Camera系列文章

传感器融合是将多个传感器采集的数据进行融合处理,以更好感知周围环境;这里首先介绍Camera的相关内容,包括摄像头及图像知识基本介绍,OpenCV图像识别(特征提取,目标分类等),融合激光点云和图像进行TTC估计。

系列文章目录
1. 摄像头基础及校准
2. Lidar TTC估计
3. Camera TTC估计
4. OpenCV图像特征提取
5. 常见特征检测算法介绍
6. 常见特征描述符介绍
7. YOLOv3物体检测
8. 三维激光点云到二维图像的投影
9. 基于Bounding Box的激光点云聚类


文章目录

  • Camera系列文章
  • 前言
  • 基于ROI实现激光点云聚类
  • Creating 3D Objects

前言

本节我们将通过从2D图像检测获取到的ROI(Region of interests)来对激光点云进行聚类,避免错误聚类。基于此初步的3D点云聚类,我们可以提取最近点的一些信息,比如距离,激光点云数量,目标物宽度等信息,这样我们就可以获取每个时间帧的信息,

基于ROI实现激光点云聚类

本节的主要目标是聚类场景中属于同一物体的激光点云,这里我们需要利用上一节的基于摄像头图像的YOLO物体识别方法,提取bounding box作为ROI(region of interest),以及描述物体类型的标签。
下面我们将利用ROI使空间中的3D激光点云和图像中的2D 物体关联。如下图所示,主要通过使用内外参等校准信息将所有激光点云投射到图像平面上。通过迭代所有激光灯和ROI,检查激光点云是否属于某一特定的bounding box。

如果某一点云在某一ROI内,则将其增加到boundingbox数据结构中,其中包含以下元素。

struct BoundingBox { // bounding box around a classified object (contains both 2D and 3D data)int boxID; // unique identifier for this bounding boxint trackID; // unique identifier for the track to which this bounding box belongscv::Rect roi; // 2D region-of-interest in image coordinatesint classID; // ID based on class file provided to YOLO frameworkdouble confidence; // classification truststd::vector<LidarPoint> lidarPoints; // Lidar 3D points which project into 2D image roistd::vector<cv::KeyPoint> keypoints; // keypoints enclosed by 2D roistd::vector<cv::DMatch> kptMatches; // keypoint matches enclosed by 2D roi
};

“boxID”,“roi”,“classID”,“confidence”在目标检测中获取;激光点云聚类过程中,“lidarPoints”中加入相应的ROI矩形框内的所有激光点云。即上图中的,所有投影到摄像头图像中的激光点云与包围这些点云的ROI框关联。不在矩形框内的激光点云被忽略。
某些情况下,目标检测后返回的ROI过大从而导致矩形框重叠,这种情况下需要调整ROI大小,降低不在物体上的激光点云数量,具体实现如下所示,通过使用缩放因子shrinkFactor,相对原矩形框缩小的比例[%]。通常,使用的是5%~10%的比例,避免丢失太多的信息。某些情况下,bounding box严重偏大时,调整ROI区域大小是提高激光点云聚类质量的好办法。

        double shrinkFactor = 0.10;vector<vector<BoundingBox>::iterator> enclosingBoxes; // pointers to all bounding boxes which enclose the current Lidar pointfor (vector<BoundingBox>::iterator it2 = boundingBoxes.begin(); it2 != boundingBoxes.end(); ++it2){// shrink current bounding box slightly to avoid having too many outlier points around the edgescv::Rect smallerBox;smallerBox.x = (*it2).roi.x + shrinkFactor * (*it2).roi.width / 2.0;smallerBox.y = (*it2).roi.y + shrinkFactor * (*it2).roi.height / 2.0;smallerBox.width = (*it2).roi.width * (1 - shrinkFactor);smallerBox.height = (*it2).roi.height * (1 - shrinkFactor);// check wether point is within current bounding boxif (smallerBox.contains(pt)){//it2->lidarPoints.push_back(*it1);//lidarPoints.erase(it1);//it1--;//break;enclosingBoxes.push_back(it2);}} // eof loop over all bounding boxes

另一个潜在的问题是,严格的矩形框很难匹配被矩形框包围的物体,矩形框在ROI内存在重叠。点云关联过程中,一个车辆的反射激光点云可能不可避免的关联到其他车辆上。如下图所示,车辆右上角部分绿色的激光点云实际属于前一辆卡车。左侧点云俯视图很好的展示了其相互关系。以下代码中,通过确认点云和bounding box是否为一对一包含关系,筛选掉重叠的点云,消除这个问题的影响。

void clusterLidarWithROI(std::vector<BoundingBox> &boundingBoxes, std::vector<LidarPoint> &lidarPoints)
{// store calibration data in OpenCV matricescv::Mat P_rect_xx(3,4,cv::DataType<double>::type); // 3x4 projection matrix after rectificationcv::Mat R_rect_xx(4,4,cv::DataType<double>::type); // 3x3 rectifying rotation to make image planes co-planarcv::Mat RT(4,4,cv::DataType<double>::type); // rotation matrix and translation vectorloadCalibrationData(P_rect_xx, R_rect_xx, RT);// loop over all Lidar points and associate them to a 2D bounding boxcv::Mat X(4, 1, cv::DataType<double>::type);cv::Mat Y(3, 1, cv::DataType<double>::type);for (auto it1 = lidarPoints.begin(); it1 != lidarPoints.end(); ++it1){// assemble vector for matrix-vector-multiplicationX.at<double>(0, 0) = it1->x;X.at<double>(1, 0) = it1->y;X.at<double>(2, 0) = it1->z;X.at<double>(3, 0) = 1;// project Lidar point into cameraY = P_rect_xx * R_rect_xx * RT * X;cv::Point pt;pt.x = Y.at<double>(0, 0) / Y.at<double>(0, 2); // pixel coordinatespt.y = Y.at<double>(1, 0) / Y.at<double>(0, 2);double shrinkFactor = 0.10;vector<vector<BoundingBox>::iterator> enclosingBoxes; // pointers to all bounding boxes which enclose the current Lidar pointfor (vector<BoundingBox>::iterator it2 = boundingBoxes.begin(); it2 != boundingBoxes.end(); ++it2){// shrink current bounding box slightly to avoid having too many outlier points around the edgescv::Rect smallerBox;smallerBox.x = (*it2).roi.x + shrinkFactor * (*it2).roi.width / 2.0;smallerBox.y = (*it2).roi.y + shrinkFactor * (*it2).roi.height / 2.0;smallerBox.width = (*it2).roi.width * (1 - shrinkFactor);smallerBox.height = (*it2).roi.height * (1 - shrinkFactor);// check wether point is within current bounding boxif (smallerBox.contains(pt)){//it2->lidarPoints.push_back(*it1);//lidarPoints.erase(it1);//it1--;//break;enclosingBoxes.push_back(it2);}} // eof loop over all bounding boxes//check wether point has been enclosed by on or by multiple boxesif(enclosingBoxes.size()==1){enclosingBoxes[0]->lidarPoints.push_back(*it1);}} // eof loop over all Lidar points
}

Creating 3D Objects

目前我们已经将2D图像数据与3D激光点云数据关联。对于图像中的每个物体,我们已经获取一系列的属于这个物体的激光点云。本节的主要目标是将bounding box显示在激光点云俯视图中。以下代码中,3D物体的以下特性被提取出来:

  1. X轴方向(行车方向)最近点的距离;
  2. 物体的宽度和高度;
  3. 激光点云数量。

void show3DObjects(std::vector<BoundingBox> &boundingBoxes,cv::Size worldSize,cv::Size imageSize, bool bWait)
{//create topview imagecv::Mat topviewImg(imageSize,CV_8UC3,cv::Scalar(255,255,255));for(auto it1=boundingBoxes.begin();it1!=boundingBoxes.end();++it1){//create randomized color for current 3D objectcv::RNG rng(it1->boxID);cv::Scalar currColor = cv::Scalar(rng.uniform(0,150),rng.uniform(0,150),rng.uniform(0,150));//plot Lidar points into top view imageint top=1e8,left=1e8,bottom=0.0,right=0.0;float xwmin=1e8,ywmin=1e8,ywmax=-1e8;for(auto it2=it1->lidarPoints.begin();it2!=it1->lidarPoints.end();++it2){//word coordinate float xw = (*it2).x; //world position in m with x facing forward from sensorfloat yw = (*it2).y; //world position in m with y facing left from sensorxwmin = xwmin<xw ? xwmin : xw;ywmin = ywmin<yw ? ywmin : yw;ywmax = ywmin>yw ? ywmax : yw;//top-view coordinatesint y = (-xw*imageSize.height/worldSize.height) + imageSize.height;int x = (-yw*imageSize.width/worldSize.width) + imageSize.width/2;//find enclosing rectangletop = top<y ? top : y;left = left<x ? left : x;bottom = bottom>y ? bottom : y;right = right>x ? right :x;//draw individual pointcv::circle(topviewImg,cv::Point(x,y),4,currColor,-1);}//draw enclosing rectanglecv::rectangle(topviewImg,cv::Point(left,top),cv::Point(right,bottom),cv::Scalar(0,0,0),2);//augment object with some key datachar str1[200],str2[200];sprintf(str1,"id=%d,#pts=%d",(int)it1->lidarPoints.size());putText(topviewImg,str1,cv::Point2f(left-250,bottom+125),cv::FONT_ITALIC,2,currColor);    }// plot distance markersfloat lineSpacing = 2.0; //gap between distance markersint nMarkers = floor(worldSize.height/lineSpacing);for(size_t i=0; i<nMarkers; ++i){int y = (-(i*lineSpacing)*imageSize.height/worldSize.height)+ imageSize.height;cv::line(topviewImg,cv::Point(0,y),cv::Point(imageSize.width,y),cv::Scalar(255,0,0));}//display imagestring windowName = "3D Objects"cv::namedWindow(windowName,1);cv::imshow(windowName,topviewImg);if(bwait){cv::waitKey(0); //wait for key to be pressed}
}

基于Bounding Box的激光点云聚类相关推荐

  1. 基于全景图像与激光点云配准的彩色点云生成算法(2014年文章)

    标题:The algorithm to generate color point-cloud with the registration between panoramic imageand lase ...

  2. 基于三维激光点云的目标识别与跟踪研究

    基于三维激光点云的目标识别与跟踪研究 人工智能技术与咨询 来源:<汽车工程> ,作者徐国艳等 [摘要] 针对无人车环境感知中的障碍物检测问题,设计了一套基于车载激光雷达的目标识别与跟踪方法 ...

  3. 基于RANSAC的激光点云分割

    Lidar系列文章 传感器融合是将多个传感器采集的数据进行融合处理,以更好感知周围环境:这里首先介绍激光雷达的相关内容,包括激光雷达基本介绍(本节内容),激光点云数据处理方法(点云数据显示,点云分割, ...

  4. 【论文笔记】2019 基于激光点云pole检测的重定位方法 Long-Term Urban Vehicle Localization Using Pole Landmarks

    https://github.com/acschaefer/polex 本文提出了一个基于激光三维点云的二维车辆定位系统,其根据道路场景中的 "pole landmarks" (极 ...

  5. 基于三维激光点云的树木建模(枝叶分离)

    [基于三维激光点云的树木建模] 2019.05.30 三维激光点云数据采集 2019.06.15 点云的枝叶分离(树枝.树干提取) 枝干骨架提取 枝干骨架优化 构建三维模型 测试软件: 链接:http ...

  6. 二十一. 智能驾驶之基于视觉识别和点云聚类的障碍物检测

    一. 背景介绍 在智能驾驶领域, 根据使用的传感器的不同,对障碍物的检测和识别通常有三种做法: 1.一种是基于相机图像和点云鸟瞰图的纯图像障碍物检测, 比如YOLO三维; 2.一种是将相机和雷达进行联 ...

  7. matlab点云聚类,基于区域聚类分割的点云特征线提取

    王晓辉 , 吴禄慎 , 陈华伟 , 胡赟 , 石雅莹 . . 基于区域聚类分割的点云特征线提取. 光学学报, 2018, 38(11): 1110001-. Wang Xiaohui , Wu Lus ...

  8. 基于cocos2d-x的2D空间中的OBB(Orient Bounding Box)碰撞检测算法

    引言 最近在与好友聊天的过程中,好友问我如何实现类似这样的游戏.它主要想知道,如何检测旋转过后的物体与其他物体之间的碰撞. 我们知道,在没有旋转的情况下,对于这样的方块,比较规则的物体,我们完全可以使 ...

  9. PointFusion: Deep Sensor Fusion for 3D Bounding Box Estimation

    摘要 我们提出了PointFusion,一种利用图像和3D点云信息的通用3D对象检测方法.与使用多级管道或保持传感器和数据集特定假设的现有方法不同,PointFusion在概念上简单且与应用程序无关. ...

最新文章

  1. 内核知识第九讲,32位下的分页管理,36位下的分页管理.以及64位下的分页管理
  2. jvm系列(七):jvm调优-工具篇
  3. 多项式求和x+(x^2)/2!+(x^3)/3!+...
  4. 求职及学习心情文章收集
  5. 【Android面试】Android面试题集锦 (陆续更新)
  6. linux把终端嵌入桌面,在Ubuntu Linux桌面上嵌入终端窗口
  7. 如何在CISCO PIX上实现×××步骤?
  8. [Swift]LeetCode978. 最长湍流子数组 | Longest Turbulent Subarray
  9. python数据处理实战
  10. xamarin.forms 绑定页面里指定元素的某个属性值
  11. 学长分享:计算机专业大一学生如何学习C语言?如何自学C语言?大学C语言学习视频教程谁有?
  12. 供应IMX335/IMX386/IMX258/OV4689/OV5640/OV8865/光学防抖摄像头模组
  13. Notepad++设置记录
  14. 数字孪生|数字孪生装备-关键技术和发展阶段
  15. mars2d解决底图上下拖动超出边界出现灰色底
  16. gis生成道路中心线_ArcGIS方法-利用到路面提取道路中心线的方法
  17. 数学建模python实现基础编程练习4
  18. 配置局域网内电脑快速传输数据
  19. 国产AR SDK介绍+国外arSdk带过
  20. Windows终端美化

热门文章

  1. python中codecs_Python:如何使用codecs模块将unicode数据保存成gbk格式
  2. thaiphoon burner 使用_果粉请注意,苹果iPhone 12在日常使用时有两大隐忧
  3. linux命令txt,Linux常用命令(非常详细!)
  4. thinkphp v5.0.11漏洞_ThinkPHP(5.1.x ~ 5.1.31 5.0.x ~ 5.0.23)GetShell漏洞
  5. python常用第三方模块多少万_python 常用第三方模块
  6. 北语20春oracle数据开发2,北语20春《Oracle数据库开发》作业3题目【标准答案】
  7. 用matlab求不动点迭代,科学网—数值分析--非线性方程组不动点迭代法matlab程序 - 殷春武的博文...
  8. 多核CPU上python多线程并行的一个假象(转)
  9. html css 深入理解float
  10. POJ - 2559 Largest Rectangle in a Histogram(单调栈)