@@ -15,15 +15,15 @@ using namespace pcl;
1515using namespace cv ;
1616
1717// float picScale = 30;
18- float picScale = 900 /roiM;
18+ float picScale = 900 /roiM; // ???
1919int ramPoints = 80 ;
2020int lSlopeDist = 1.0 ;
2121// //////////////////////int lSlopeDist = 3.0;
2222// //////////////////////int lnumPoints = 300;
2323int lnumPoints = 5 ;
2424
2525// ////////////////////////////float sensorHeight = 1.73;
26- float sensorHeight = 2 ;
26+ float sensorHeight = 2 ; // 激光雷达距离地面高度
2727// float tHeightMin = 1.2;
2828float tHeightMin = 0.8 ;
2929float tHeightMax = 2.6 ;
@@ -58,7 +58,7 @@ void getClusteredPoints(PointCloud<PointXYZ>::Ptr elevatedCloud,
5858 int yI = floor (numGrid * yC / roiM);
5959
6060 int clusterNum = cartesianData[xI][yI]; // 1 ~ numCluster 初始聚类ID数量numCluster
61- // cout << "clusterNum is " << clusterNum << endl; // 连续几个相同的值(聚类在一块的? )
61+ // cout << "clusterNum is " << clusterNum << endl; // 连续几个相同的值(聚类在一块的)
6262 int vectorInd = clusterNum - 1 ; // 0 ~ (numCluster -1 )
6363 if (clusterNum != 0 ) {
6464 PointXYZ o;
@@ -71,6 +71,7 @@ void getClusteredPoints(PointCloud<PointXYZ>::Ptr elevatedCloud,
7171 }
7272}
7373
74+ //
7475void getPointsInPcFrame (Point2f rectPoints[], vector<Point2f>& pcPoints, int offsetX, int offsetY){
7576 // loop 4 rect points
7677 for (int pointI = 0 ; pointI < 4 ; pointI++){
@@ -94,10 +95,10 @@ void getPointsInPcFrame(Point2f rectPoints[], vector<Point2f>& pcPoints, int off
9495}
9596
9697bool ruleBasedFilter (vector<Point2f> pcPoints, float maxZ, int numPoints){
97- bool isPromising = false ;
98+ bool isPromising = false ; // 是否舍弃此聚类
9899 // minnimam points thresh
99- if (numPoints < 30 ) return isPromising; // 小于30个点,返回false
100- // length is longest side of the rectangle while width is the shorter side.
100+ if (numPoints < 30 ) return isPromising; // 小于30个点,返回false 舍弃此聚类 cout << "numPoints is "<< numPoints <<endl; // 差不多(3~, 800~)
101+ // length is longest side of the rectangle while width is the shorter side. 长度是矩形的最长边,而宽度是较短的边。
101102 float width, length, height, area, ratio, mass;
102103
103104 float x1 = pcPoints[0 ].x ;
@@ -109,36 +110,37 @@ bool ruleBasedFilter(vector<Point2f> pcPoints, float maxZ, int numPoints){
109110
110111 float dist1 = sqrt ((x1-x2)*(x1-x2)+ (y1-y2)*(y1-y2));
111112 float dist2 = sqrt ((x3-x2)*(x3-x2)+ (y3-y2)*(y3-y2));
112- if (dist1 > dist2){
113+ if (dist1 > dist2){ // 判断长边和宽边
113114 length = dist1;
114115 width = dist2;
115116 }
116117 else {
117118 length = dist2;
118119 width = dist1;
119120 }
120- // assuming ground = sensor height
121- height = maxZ + sensorHeight;
121+ // assuming ground = sensor height 假设地面=传感器高度
122+ // cout << "maxZ is "<< maxZ <<endl; // 差不多这个范围(0.553392,0.999263)
123+ height = maxZ + sensorHeight; // float sensorHeight = 2;
122124 // assuming right angle
123- area = dist1*dist2;
124- mass = area*height;
125- ratio = length/width;
125+ area = dist1*dist2; // 平面框面积
126+ mass = area*height; // 框 体积
127+ ratio = length/width; // 长宽比
126128
127- // cout<< "height is " <<height<<endl;
128- // cout<< "width is " <<width<<endl;
129- // cout<< "length is " <<length<<endl;
130- // cout<< "area is " <<area<<endl;
131- // cout<< "mass is " <<mass<<endl;
132- // cout<< "ratio is " <<ratio<<endl;
129+ // cout<< "height is " <<height<<endl; // 2.3821
130+ // cout<< "width is " <<width<<endl; // 2.17553
131+ // cout<< "length is " <<length<<endl; //4.92502
132+ // cout<< "area is " <<area<<endl; //10.7145
133+ // cout<< "mass is " <<mass<<endl; //25.523
134+ // cout<< "ratio is " <<ratio<<endl; // 2.26383
133135
134136 // start rule based filtering // 开始 Rule-based Filter
135- if (height > tHeightMin && height < tHeightMax){
136- if (width > tWidthMin && width < tWidthMax){
137- if (length > tLenMin && length < tLenMax){
138- if (area < tAreaMax){
139- if (numPoints > mass*tPtPerM3){
140- if (length > minLenRatio){
141- if (ratio > tRatioMin && ratio < tRatioMax){
137+ if (height > tHeightMin && height < tHeightMax){ // (0.8 2.6) tHeightMin = 0.8; tHeightMax = 2.6;
138+ if (width > tWidthMin && width < tWidthMax){ // (0.2 3.5)
139+ if (length > tLenMin && length < tLenMax){ // (0.2, 14)
140+ if (area < tAreaMax){ // tAreaMax = 20.0;
141+ if (numPoints > mass*tPtPerM3){ // tPtPerM3 = 8;
142+ if (length > minLenRatio){ // minLenRatio = 3.0;
143+ if (ratio > tRatioMin && ratio < tRatioMax){ // 长宽比 (1.0, 8.0)
142144 isPromising = true ;
143145 return isPromising;
144146 }
@@ -211,160 +213,161 @@ void getBoundingBox(vector<PointCloud<PointXYZ>> clusteredPoints,
211213 vector<PointCloud<PointXYZ>>& bbPoints,visualization_msgs::MarkerArray& ma){
212214 // cout << "the number of cluster is "<< clusteredPoints.size() <<endl; // 初始聚类ID数量numCluster is
213215
214- for (int iCluster = 0 ; iCluster < clusteredPoints.size (); iCluster++){ // 循环的次数就是 初始聚类ID数量numCluster is 33
216+ for (int iCluster = 0 ; iCluster < clusteredPoints.size (); iCluster++){ // 循环的次数就是 初始聚类ID数量numCluster
215217 Mat m (picScale*roiM, picScale*roiM, CV_8UC1, Scalar (0 ));
216- float initPX = clusteredPoints[iCluster][0 ].x + roiM/2 ;
217- float initPY = clusteredPoints[iCluster][0 ].y + roiM/2 ;
218- int initX = floor (initPX*picScale);
219- int initY = floor (initPY*picScale);
218+ float initPX = clusteredPoints[iCluster][0 ].x + roiM/2 ; // (0 ~ 50) 第0个点的x,y坐标
219+ float initPY = clusteredPoints[iCluster][0 ].y + roiM/2 ; // (0 ~ 50)
220+ int initX = floor (initPX*picScale); // picScale = 900/roiM, 放大倍数900
221+ int initY = floor (initPY*picScale); //
220222 int initPicX = initX;
221- int initPicY = picScale*roiM - initY;
222- int offsetInitX = roiM*picScale/2 - initPicX;
223+ int initPicY = picScale*roiM - initY; // Y值取余 : Y = 900-Y
224+ int offsetInitX = roiM*picScale/2 - initPicX; //
223225 int offsetInitY = roiM*picScale/2 - initPicY;
224226
225- int numPoints = clusteredPoints[iCluster].size (); // 比如聚类33,每一类里面有多少点 numPoints
226- vector<Point> pointVec (numPoints);
227+ int numPoints = clusteredPoints[iCluster].size (); // 每一聚类里面有多少点 numPoints
228+ vector<Point> pointVec (numPoints); // 定义
227229 vector<Point2f> pcPoints (4 ); // ???
228230 float minMx, minMy, maxMx, maxMy;
229231 float minM = 999 ; float maxM = -999 ; float maxZ = -99 ;
230232 float maxdistance=-999 ;
231- // for center of gravity
233+ // for center of gravity重力
232234 float sumX = 0 ; float sumY = 0 ;
233235
234236 // cout << "the number of cluster i is "<< numPoints <<endl;
235237
236238 // 循环每一聚类里面的点
237239 for (int iPoint = 0 ; iPoint < clusteredPoints[iCluster].size (); iPoint++){
238- float pX = clusteredPoints[iCluster][iPoint].x ;
240+ float pX = clusteredPoints[iCluster][iPoint].x ; // 聚类中每个点的x,y,z
239241 float pY = clusteredPoints[iCluster][iPoint].y ;
240242 float pZ = clusteredPoints[iCluster][iPoint].z ;
241243 // cast (-15 < x,y < 15) into (0 < x,y < 30)
242244 float roiX = pX + roiM/2 ;
243245 float roiY = pY + roiM/2 ;
244- // cast 30mx30m into 900x900 scale
246+ // cast 30mx30m into 900x900 scale 投射放大
245247 int x = floor (roiX*picScale);
246248 int y = floor (roiY*picScale);
247249 // cast into image coordinate
248250 int picX = x;
249- int picY = picScale*roiM - y;
250- // offset so that the object would be locate at the center
251+ int picY = picScale*roiM - y; // Y轴换个反方向
252+ // offset so that the object would be locate at the center offset偏移量以便将object定位在中心
251253 int offsetX = picX + offsetInitX;
252254 int offsetY = picY + offsetInitY;
253255
254256/* std::cout << "----------------------" << std::endl;
255- std::cout << offsetX << std::endl;
256- std::cout << offsetY << std::endl;
257- std::cout << "---------------------" << std::endl;
257+ std::cout << offsetX << std::endl; // 举例 444
258+ std::cout << offsetY << std::endl; // 举例 452
259+ std::cout << "---------------------" << std::endl;
258260*/
261+
259262 // m.at<uchar>(offsetY, offsetX) = 255;
260- pointVec[iPoint] = Point (offsetX, offsetY);
263+ pointVec[iPoint] = Point (offsetX, offsetY); // 偏移量
261264 // calculate min and max slope 斜率
262- float m = pY/pX;
265+ float m = pY/pX; // 斜率
263266 // //////////std::cout << "m:" << m << std::endl;
264267
265- if (m < minM) {
268+ if (m < minM) { // float minM = 999; float maxM = -999 根据斜率判断
266269 minM = m;
267270 minMx = pX;
268271 minMy = pY;
269272 // ///////std::cout << "mmmmmm" << m << std::endl;
270273
271274 }
272- if (m > maxM) {
275+ if (m > maxM) { // float minM = 999; float maxM = -999
273276 maxM = m;
274277 maxMx = pX;
275278 maxMy = pY;
276279 // ///////std::cout << "MMMMM" << std::endl;
277280 }
278281
279- float xydis = sqrt (pX*pX+pY*pY);
282+ float xydis = sqrt (pX*pX+pY*pY); //
280283
281284 if (xydis > maxdistance)maxdistance = xydis; // 最大距离
282285
283286
284287 // get maxZ
285- if (pZ > maxZ) maxZ = pZ; // 最大距离
288+ if (pZ > maxZ) maxZ = pZ; // 最大高度
286289
287- sumX += offsetX;
290+ sumX += offsetX; // ???
288291 sumY += offsetY;
289292
290- }
293+ } // 小循环结束
291294 // L shape fitting parameters === 将最小面积矩形(MAR)[128]应用于每个聚类对象,从而生成一个2D框,
292- // 某些稀疏点(带红色圆圈)被认为是异常值,并且MAR过程导致不正确的框,使用L形拟合可解决此问题
293- float xDist = maxMx - minMx;
295+ // 某些稀疏点(带红色圆圈)被认为是异常值,并且MAR过程导致不正确的框,使用L形拟合可解决此问题 可参考:https://www.yuque.com/huangzhongqing/hre6tf/pcohs1#FONbX
296+ float xDist = maxMx - minMx; // 选择两个最远的离群点x1和x2
294297 float yDist = maxMy - minMy;
295- float slopeDist = sqrt (xDist*xDist + yDist*yDist); // 选择两个最远的离群点x1和x2,它们位于面向LIDAR传感器的对象的相对侧。然后在两点之间绘制一条线Ldis
298+ float slopeDist = sqrt (xDist*xDist + yDist*yDist); // 选择两个最远的离群点x1和x2,它们位于面向LIDAR传感器的对象的相对侧。然后在两点之间绘制一条线Ld
296299 // ///////////////////std::cout << "boxFitting slopeDist" << slopeDist << std::endl;
297- float slope = (maxMy - minMy)/(maxMx - minMx); // 斜率
300+ float slope = (maxMy - minMy)/(maxMx - minMx); // 最大斜率
298301
299302 // random variable
300- mt19937_64 mt (0 );
303+ mt19937_64 mt (0 ); // ???
301304 uniform_int_distribution<> randPoints (0 , numPoints-1 );
302305
303306 // start l shape fitting for car like object 开始为汽车之类的物体 l shape fitting
304307 // lSlopeDist = 10000, lnumPoints = 30000;
305- if (slopeDist > lSlopeDist && numPoints > lnumPoints && (maxMy > 8 || maxMy < -5 )){
308+ if (slopeDist > lSlopeDist && numPoints > lnumPoints && (maxMy > 8 || maxMy < -5 )){ // int lSlopeDist = 1.0; int lnumPoints = 5;判断框的大小以及框内的点数
306309// if(1){
307310 float maxDist = 0 ;
308311 float maxDx, maxDy;
309312
310313 // 80 random points, get max distance
311- for (int i = 0 ; i < ramPoints; i++){ // int ramPoints = 80;
312- int pInd = randPoints (mt);
313- assert (pInd >= 0 && pInd < clusteredPoints[iCluster].size ());
314+ for (int i = 0 ; i < ramPoints; i++){ // ramPoints = 80;
315+ int pInd = randPoints (mt); // 随机点
316+ assert (pInd >= 0 && pInd < clusteredPoints[iCluster].size ()); // 如果其值为假(即为0),那么它先向stderr打印一条出错信息,
314317 float xI = clusteredPoints[iCluster][pInd].x ;
315318 float yI = clusteredPoints[iCluster][pInd].y ;
316319
317- // from equation of distance between line and point
318- float dist = abs (slope*xI-1 *yI+maxMy-slope*maxMx)/sqrt (slope*slope + 1 );
319- if (dist > maxDist) { // 赋值最大值 maxDist
320- maxDist = dist;
320+ // from equation of distance between line and point /点到直线的距离方程
321+ float dist = abs (slope*xI-1 *yI+maxMy-slope*maxMx)/sqrt (slope*slope + 1 ); // 点到直线的距离
322+ if (dist > maxDist) { // 寻找最远的距离 maxDist
323+ maxDist = dist; // 赋值给最远的距离 maxDist
321324 maxDx = xI;
322325 maxDy = yI;
323326 }
324327 }
325328
326- // for center of gravity
329+ // for center of gravity 重心
327330 // maxDx = sumX/clusteredPoints[iCluster].size();
328331 // maxDy = sumY/clusteredPoints[iCluster].size();
329332
330- // vector adding
333+ // vector adding 向量加法 闭合连接X1、X2和X3得到L形折线
331334 float maxMvecX = maxMx - maxDx;
332335 float maxMvecY = maxMy - maxDy;
333336 float minMvecX = minMx - maxDx;
334337 float minMvecY = minMy - maxDy;
335- float lastX = maxDx + maxMvecX + minMvecX;
338+ float lastX = maxDx + maxMvecX + minMvecX; // X4
336339 float lastY = maxDy + maxMvecY + minMvecY;
337340
338341 pcPoints[0 ] = Point2f (minMx, minMy); // ??pcPoints
339342 pcPoints[1 ] = Point2f (maxDx, maxDy);
340343 pcPoints[2 ] = Point2f (maxMx, maxMy);
341- pcPoints[3 ] = Point2f (lastX, lastY);
344+ pcPoints[3 ] = Point2f (lastX, lastY); // 得到第四个点
342345
343- // ////////// std::cout << " pcPoints[0] " << pcPoints[0].x << " " << pcPoints[0].y << std::endl;
344- // ///////// std::cout << " pcPoints[1] " << pcPoints[1].x << " " << pcPoints[1].y << std::endl;
345- // ///////// std::cout << " pcPoints[2] " << pcPoints[2].x << " " << pcPoints[2].y << std::endl;
346- // //////// std::cout << " pcPoints[3] " << pcPoints[3].x << " " << pcPoints[3].y << std::endl;
346+ // std::cout << " pcPoints[0] " << pcPoints[0].x << " " << pcPoints[0].y << std::endl;
347+ // std::cout << " pcPoints[1] " << pcPoints[1].x << " " << pcPoints[1].y << std::endl;
348+ // std::cout << " pcPoints[2] " << pcPoints[2].x << " " << pcPoints[2].y << std::endl;
349+ // std::cout << " pcPoints[3] " << pcPoints[3].x << " " << pcPoints[3].y << std::endl;
347350
348351 // std::cout << "boxFitting maxZ " << maxZ << std::endl; // boxFitting maxZ 0.525725
349352 // 最后一步:消除大多数无关对象,例如墙壁,灌木丛,建筑物和树木。实现尺寸阈值化以实现此目的。
350- bool isPromising = ruleBasedFilter (pcPoints, maxZ, numPoints); // 比如聚类33,每一类里面有多少点 numPoints
353+ bool isPromising = ruleBasedFilter (pcPoints, maxZ, numPoints); // 比如聚类33,每一类里面有多少点 numPoints(四个点,z最大值, 每个聚类中的点数)
351354 // std::cout << "boxFitting isPromising:" << isPromising << std::endl; // 1, 0
352- if (!isPromising) continue ;
355+ if (!isPromising) continue ; // 没有,就舍弃此聚类,到下一个循环
353356 }
354357 else {
355358 // MAR fitting
356- RotatedRect rectInfo = minAreaRect (pointVec);
359+ RotatedRect rectInfo = minAreaRect (pointVec); // 自带函数
357360 Point2f rectPoints[4 ]; rectInfo.points ( rectPoints );
358- // covert points back to lidar coordinate
361+ // covert points back to lidar coordinate 隐蔽点返回激光雷达坐标
359362 getPointsInPcFrame (rectPoints, pcPoints, offsetInitX, offsetInitY);
360363 // rule based filter
361364 bool isPromising = ruleBasedFilter (pcPoints, maxZ, numPoints);
362- if (!isPromising) continue ;
363- // for visualization
364- // for( int j = 0; j < 4; j++ )
365- // line( m, rectPoints[j], rectPoints[(j+1)%4ne], Scalar(255,255,0), 1, 8 );
366- // imshow("Display Image", m);
367- // waitKey(0);
365+ if (!isPromising) continue ; // 没有,就舍弃此聚类,到下一个循环
366+ // // for visualization
367+ // for( int j = 0; j < 4; j++ )
368+ // line( m, rectPoints[j], rectPoints[(j+1)%4ne], Scalar(255,255,0), 1, 8 );
369+ // imshow("Display Image", m);
370+ // waitKey(0);
368371 // ///////std::cout << " else pcPoints[0] " << pcPoints[0].x << " " << pcPoints[0].y << std::endl;
369372 // //////std::cout << " else pcPoints[1] " << pcPoints[1].x << " " << pcPoints[1].y << std::endl;
370373 // /////std::cout << " else pcPoints[2] " << pcPoints[2].x << " " << pcPoints[2].y << std::endl;
@@ -374,12 +377,12 @@ void getBoundingBox(vector<PointCloud<PointXYZ>> clusteredPoints,
374377
375378 // make pcl cloud for 3d bounding box 3D边界框
376379 PointCloud<PointXYZ> oneBbox;
377- for (int pclH = 0 ; pclH < 2 ; pclH++){
380+ for (int pclH = 0 ; pclH < 2 ; pclH++){ // 上下个4个坐标点
378381 for (int pclP = 0 ; pclP < 4 ; pclP++){
379382 PointXYZ o;
380383 o.x = pcPoints[pclP].x ;
381384 o.y = pcPoints[pclP].y ;
382- if (pclH == 0 ) o.z = -sensorHeight;
385+ if (pclH == 0 ) o.z = -sensorHeight; // -2
383386 else o.z = maxZ;
384387 oneBbox.push_back (o); // 一个边界框
385388 }
0 commit comments