00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <stdio.h>
00034 #include <fstream>
00035 #include <iostream>
00036 #include <ctype.h>
00037 #include <ctime>
00038 #include "camera_laser_calibration/scene_recog/scene_recog.h"
00039
00040 #include <ros/ros.h>
00041
00042 CSceneRecog *p_plane_display = NULL;
00043
00044 CSceneRecog::CSceneRecog ()
00045 {
00046 L_width_ = 0;
00047 L_height_ = 0;
00048 p_plane_display = this;
00049 plane_parameters_[0] = 0.0;
00050 plane_parameters_[1] = 0.0;
00051 plane_parameters_[2] = 0.0;
00052 plane_parameters_[3] = 0.0;
00053 }
00054
00055 CSceneRecog::~CSceneRecog (void)
00056 {
00057 }
00058
00059 void CSceneRecog::srProcess (std::vector < std::vector < CPoint3d > >&data)
00060 {
00061 laser_data_.swap (data);
00062 srPlaneExtract ();
00063 srStructureExtract ();
00064 }
00065
00066 void CSceneRecog::srPlaneExtract ()
00067 {
00068 CPoint3d PointInSquare[DIMEN][DIMEN];
00069 CPoint3d Mv;
00070 CPoint3d Nvec;
00071 int flagbuf;
00072 int pnum = -1;
00073 if (laser_data_.size () > 0)
00074 {
00075 L_width_ = (int) laser_data_.size ();
00076 L_height_ = (int) laser_data_[0].size ();
00077
00078 std::vector < CPointTag > TagVector (L_height_);
00079 std::vector < std::vector < CPointTag > >PTV (L_width_, TagVector);
00080 point_tag_vector_.swap (PTV);
00081
00082 for (int i = 0; i < L_width_ - DIMEN; i = i + 1)
00083 {
00084 for (int j = 0; j < L_height_ - DIMEN; j = j + 1)
00085 {
00086 Mv.x = Mv.y = Mv.z = 0.0;
00087 for (int k = 0; k < DIMEN; k++)
00088 for (int l = 0; l < DIMEN; l++)
00089 {
00090 PointInSquare[k][l] = laser_data_[i + k][j + l];
00091 Mv.x += PointInSquare[k][l].x;
00092 Mv.y += PointInSquare[k][l].y;
00093 Mv.z += PointInSquare[k][l].z;
00094 }
00095 Mv.x = Mv.x / (DIMEN * DIMEN);
00096 Mv.y = Mv.y / (DIMEN * DIMEN);
00097 Mv.z = Mv.z / (DIMEN * DIMEN);
00098
00099 if (srIsAPlane (PointInSquare, Mv))
00100 {
00101 Nvec =srNormalVec (laser_data_[i + DIMEN - 1][j + DIMEN - 1], laser_data_[i + DIMEN - 1][j],
00102 laser_data_[i][j + DIMEN - 1], laser_data_[i][j]);
00103
00104 flagbuf = -1;
00105 for (int f = 0; f <= DIMEN - 1; f++)
00106 for (int g = 0; g <= DIMEN - 1; g++)
00107 {
00108 if (point_tag_vector_[i + f][j + g].pflag != -1)
00109 {
00110 flagbuf = point_tag_vector_[i + f][j + g].pflag;
00111 break;
00112 }
00113 }
00114
00115 if (flagbuf == -1)
00116 {
00117 pnum++;
00118 for (int m = 0; m < DIMEN; m++)
00119 {
00120 for (int n = 0; n < DIMEN; n++)
00121 {
00122 point_tag_vector_[i + m][j + n].pflag = pnum;
00123 }
00124 }
00125 Plane pTag;
00126 pTag.VecNum = 1;
00127 pTag.VecSum = Nvec;
00128 pTag.VecAve = Nvec;
00129 pTag.MeanVal = Mv;
00130 pTag.MeanSum = Mv;
00131 plane_vector_.push_back (pTag);
00132 }
00133
00134 else
00135 {
00136 if (srAngle (plane_vector_[flagbuf].VecAve, Nvec) < 0.2 )
00137 {
00138 for (int m2 = 0; m2 < DIMEN; m2++)
00139 for (int n2 = 0; n2 < DIMEN; n2++)
00140 {
00141 point_tag_vector_[i + m2][j + n2].pflag = flagbuf;
00142 }
00143
00144 plane_vector_[flagbuf].VecNum++;
00145
00146 plane_vector_[flagbuf].VecSum.x += Nvec.x;
00147 plane_vector_[flagbuf].VecSum.y += Nvec.y;
00148 plane_vector_[flagbuf].VecSum.z += Nvec.z;
00149
00150 plane_vector_[flagbuf].VecAve.x = plane_vector_[flagbuf].VecSum.x / plane_vector_[flagbuf].VecNum;
00151 plane_vector_[flagbuf].VecAve.y = plane_vector_[flagbuf].VecSum.y / plane_vector_[flagbuf].VecNum;
00152 plane_vector_[flagbuf].VecAve.z = plane_vector_[flagbuf].VecSum.z / plane_vector_[flagbuf].VecNum;
00153
00154 plane_vector_[flagbuf].MeanSum.x += Mv.x;
00155 plane_vector_[flagbuf].MeanSum.y += Mv.y;
00156 plane_vector_[flagbuf].MeanSum.z += Mv.z;
00157
00158 plane_vector_[flagbuf].MeanVal.x = plane_vector_[flagbuf].MeanSum.x / plane_vector_[flagbuf].VecNum;
00159 plane_vector_[flagbuf].MeanVal.y = plane_vector_[flagbuf].MeanSum.y / plane_vector_[flagbuf].VecNum;
00160 plane_vector_[flagbuf].MeanVal.z = plane_vector_[flagbuf].MeanSum.z / plane_vector_[flagbuf].VecNum;
00161 }
00162 }
00163 }
00164 }
00165 }
00166 }
00167 }
00168
00169 void CSceneRecog::srStructureExtract ()
00170 {
00171
00172 using namespace std;
00173
00174 for (int i = 0; i < L_height_; i++)
00175 {
00176 for (int j = 0; j < L_width_; j++)
00177 {
00178 int flag = point_tag_vector_[j][i].pflag;
00179 if (flag >= 0)
00180 {
00181 CPointIndex index (i, j);
00182 plane_vector_[flag].InnerPoints.push_back (index);
00183 }
00184 }
00185 }
00186
00187
00188
00189 int PlaneNum = (int) plane_vector_.size ();
00190 for (int i = 0; i < PlaneNum - 1; i++)
00191 {
00192 int pmax = i;
00193 for (int j = i + 1; j < PlaneNum; j++)
00194 {
00195 if (plane_vector_[j].VecNum > plane_vector_[pmax].VecNum)
00196 {
00197 pmax = j;
00198 }
00199 }
00200 if (pmax != i)
00201 std::swap (plane_vector_[i], plane_vector_[pmax]);
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211 int iterate = 2;
00212 while (iterate-- > 1)
00213 {
00214
00215 int cnt = 0;
00216 vector < Plane > Planes;
00217 vector < Plane > ExcludePlane;
00218 for (int i = 0; i < (int) plane_vector_.size (); i++)
00219 {
00220 cnt++;
00221 if (plane_vector_[i].VecNum < 4)
00222 break;
00223
00224 plane_vector_[i].A = plane_vector_[i].VecAve.x;
00225 plane_vector_[i].B = plane_vector_[i].VecAve.y;
00226 plane_vector_[i].C = plane_vector_[i].VecAve.z;
00227 plane_vector_[i].D = -(plane_vector_[i].A * plane_vector_[i].MeanVal.x
00228 + plane_vector_[i].B * plane_vector_[i].MeanVal.y
00229 + plane_vector_[i].C * plane_vector_[i].MeanVal.z);
00230
00231 bool flag = false;
00232 float angle;
00233 for (int j = 0; j < (int) Planes.size (); j++)
00234 {
00235 angle = srAngle (plane_vector_[i].VecAve, Planes[j].VecAve);
00236 angle = angle < (PI - angle) ? angle : (PI - angle);
00237 if (angle < 20 * PI / 180)
00238 {
00239 if (srP2Pl (plane_vector_[i].MeanVal, Planes[j]) < 0.1)
00240 {
00241 Planes[j].VecNum += plane_vector_[i].VecNum;
00242
00243
00244 Planes[j].VecSum += plane_vector_[i].VecSum;
00245
00246
00247 Planes[j].VecAve.x = Planes[j].VecSum.x / Planes[j].VecNum;
00248 Planes[j].VecAve.y = Planes[j].VecSum.y / Planes[j].VecNum;
00249 Planes[j].VecAve.z = Planes[j].VecSum.z / Planes[j].VecNum;
00250
00251
00252 Planes[j].MeanSum += plane_vector_[i].MeanSum;
00253
00254
00255 Planes[j].MeanVal.x = Planes[j].MeanSum.x / Planes[j].VecNum;
00256 Planes[j].MeanVal.y = Planes[j].MeanSum.y / Planes[j].VecNum;
00257 Planes[j].MeanVal.z = Planes[j].MeanSum.z / Planes[j].VecNum;
00258
00259 Planes[j].A = Planes[j].VecAve.x;
00260 Planes[j].B = Planes[j].VecAve.y;
00261 Planes[j].C = Planes[j].VecAve.z;
00262 Planes[j].D = -(Planes[j].A * Planes[j].MeanVal.x
00263 + Planes[j].B * Planes[j].MeanVal.y
00264 + Planes[j].C * Planes[j].MeanVal.z);
00265
00266 int I = (int) plane_vector_[i].InnerPoints.size ();
00267 for (int k = 0; k < I; k++)
00268 {
00269 Planes[j].InnerPoints.push_back (plane_vector_[i].InnerPoints[k]);
00270 }
00271 flag = true;
00272 break;
00273 }
00274
00275 }
00276 }
00277
00278 if (!flag)
00279 {
00280 if ((int) Planes.size () < iterate * iterate * MAX_PLANE_NUM)
00281 {
00282 Plane ptemp;
00283 Planes.push_back (ptemp);
00284 std::swap (Planes[Planes.size () - 1], plane_vector_[i]);
00285 }
00286 else
00287 {
00288 Plane ptemp;
00289 ExcludePlane.push_back (ptemp);
00290 std::swap (ExcludePlane[ExcludePlane.size () - 1], plane_vector_[i]);
00291 }
00292 }
00293 }
00294 plane_vector_.swap (Planes);
00295 }
00296
00297 boundary_vec_.resize (plane_vector_.size ());
00298 for (int i = 0; i < (int) plane_vector_.size (); i++)
00299 {
00300 int flag = 0;
00301 boundary_vec_[i].push_back (plane_vector_[i].InnerPoints[0]);
00302 for (int j = 1; j < (int) plane_vector_[i].InnerPoints.size (); j++)
00303 {
00304 flag = 1;
00305 if (plane_vector_[i].InnerPoints[j - 1].i == plane_vector_[i].InnerPoints[j].i
00306 && plane_vector_[i].InnerPoints[j - 1].j + 1 == plane_vector_[i].InnerPoints[j].j)
00307 continue;
00308 else
00309 {
00310 boundary_vec_[i].push_back (plane_vector_[i].InnerPoints[j - 1]);
00311 boundary_vec_[i].push_back (plane_vector_[i].InnerPoints[j]);
00312 flag = 0;
00313 }
00314 }
00315 if (flag == 1)
00316 boundary_vec_[i].push_back (plane_vector_[i].InnerPoints.back ());
00317 }
00318
00319
00320
00321
00322
00323
00324
00325 convex_vec_.resize (boundary_vec_.size ());
00326 for (int i = 0; i < (int) boundary_vec_.size (); i++)
00327 {
00328 int minidx = 0;
00329 for (int j = 1; j < (int) boundary_vec_[i].size (); j++)
00330 {
00331 if (boundary_vec_[i][j].i < boundary_vec_[i][minidx].i
00332 || (boundary_vec_[i][j].i == boundary_vec_[i][minidx].i
00333 && boundary_vec_[i][j].j < boundary_vec_[i][minidx].j))
00334 minidx = j;
00335 }
00336 if (minidx != 0)
00337 std::swap (boundary_vec_[i][0], boundary_vec_[i][minidx]);
00338
00339 for (int j = 1; j < (int) boundary_vec_[i].size () - 1; j++)
00340 {
00341 int r = j;
00342 for (int k = j + 1; k < (int) boundary_vec_[i].size (); k++)
00343 {
00344 bool res = srCompL1R0bool (boundary_vec_[i][0], boundary_vec_[i][r], boundary_vec_[i][k]);
00345 if (res == 0)
00346 r = k;
00347 }
00348 if (r != j)
00349 std::swap (boundary_vec_[i][j], boundary_vec_[i][r]);
00350 }
00351
00352 std::vector < CPointIndex > stack;
00353 stack.clear ();
00354 stack.push_back (boundary_vec_[i][0]);
00355 stack.push_back (boundary_vec_[i][1]);
00356 stack.push_back (boundary_vec_[i][2]);
00357
00358 int top = 2;
00359 for (int j = 3; j < (int) boundary_vec_[i].size (); j++)
00360 {
00361 while (top >= 2 && srCross_Product (stack[top - 1], stack[top], boundary_vec_[i][j]) <= 0)
00362 {
00363 stack.pop_back ();
00364 top--;
00365 }
00366 stack.push_back (boundary_vec_[i][j]);
00367 top++;
00368 }
00369 convex_vec_[i].swap (stack);
00370 }
00371
00372
00373
00374
00375
00376
00377 plane_parameters_[0] = plane_vector_[0].A;
00378 plane_parameters_[1] = plane_vector_[0].B;
00379 plane_parameters_[2] = plane_vector_[0].C;
00380 plane_parameters_[3] = plane_vector_[0].D;
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 }
00404
00405 float CSceneRecog::srPtopDistan (CPoint3d p1, CPoint3d p2)
00406 {
00407 return ((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z));
00408 }
00409
00410 bool CSceneRecog::srIsAPlane (CPoint3d p[][DIMEN], CPoint3d m)
00411 {
00412 CPoint3d Pzero (0, 0, 0);
00413 int n = 3, jt = 100;
00414 float cov[9] = { 0.0 };
00415 float s1, s2, s3, min;
00416 float eps = 0.01f;
00417 CPoint3d sum, ptemp;
00418 int zeronum = 0;
00419 bool booldis = true;
00420 float distemp, maxdis = 0.0;
00421
00422 ptemp = p[0][0];
00423 for (int i = 0; i < DIMEN; i++)
00424 {
00425 for (int j = 1; j < DIMEN; j++)
00426 {
00427 if (Pzero == p[i][j])
00428 {
00429 zeronum++;
00430 }
00431 else
00432 {
00433 distemp = srPtopDistan (ptemp, p[i][j]);
00434 if (distemp > maxdis)
00435 {
00436 maxdis = distemp;
00437 }
00438 ptemp = p[i][j];
00439 }
00440 }
00441 }
00442
00443 if (maxdis > MAXDISTH1 * MAXDISTH1)
00444 {
00445 booldis = false;
00446 return false;
00447 }
00448 for (int i = 0; i < DIMEN; i++)
00449 {
00450 for (int j = 0; j < DIMEN; j++)
00451 {
00452 float buf[3];
00453 buf[0] = p[i][j].x - m.x;
00454 buf[1] = p[i][j].y - m.y;
00455 buf[2] = p[i][j].z - m.z;
00456 for (int k = 0; k < 3; k++)
00457 for (int l = 0; l < 3; l++)
00458 if (!(p[i][j] == Pzero))
00459 {
00460 cov[k * 3 + l] += buf[k] * buf[l];
00461 }
00462 }
00463 }
00464
00465 srEigenValue (cov, n, eps, jt);
00466 s1 = fabs (cov[0]);
00467 s2 = fabs (cov[4]);
00468 s3 = fabs (cov[8]);
00469 min = s1 < s2 ? s1 : s2;
00470 min = s3 < min ? s3 : min;
00471
00472
00473 if (min < THRESH && zeronum < DIMEN && booldis)
00474 return true;
00475 return false;
00476 }
00477
00478 int CSceneRecog::srEigenValue (float a[], int n, double eps, int jt)
00479 {
00480 int i, j, u, w, t, s, l;
00481 int p = 0;
00482 int q = 0;
00483 float fm, cn, sn, omega, x, y, d, v[30];
00484 l = 1;
00485 for (i = 0; i <= n - 1; i++)
00486 {
00487 v[i * n + i] = 1.0;
00488 for (j = 0; j <= n - 1; j++)
00489 {
00490 if (i != j)
00491 {
00492 v[i * n + j] = 0.0;
00493 }
00494 }
00495 }
00496 while (l == 1)
00497 {
00498 fm = 0.0;
00499 for (i = 0; i <= n - 1; i++)
00500 {
00501 for (j = 0; j <= n - 1; j++)
00502 {
00503 d = fabs (a[i * n + j]);
00504 if ((i != j) && (d > fm))
00505 {
00506 fm = d;
00507 p = i;
00508 q = j;
00509 }
00510 }
00511 }
00512 if (fm < eps)
00513 {
00514 return (1);
00515 }
00516 if (l > jt)
00517 {
00518 return (-1);
00519 }
00520 l = l + 1;
00521 u = p * n + q;
00522 w = p * n + p;
00523 t = q * n + p;
00524 s = q * n + q;
00525 x = -a[u];
00526 y = (a[s] - a[w]) / 2.0;
00527 omega = x / sqrt (x * x + y * y);
00528 if (y < 0.0)
00529 {
00530 omega = -omega;
00531 }
00532 sn = 1.0 + sqrt (1.0 - omega * omega);
00533 sn = omega / sqrt (2.0 * sn);
00534 cn = sqrt (1.0 - sn * sn);
00535 fm = a[w];
00536 a[w] = fm * cn * cn + a[s] * sn * sn + a[u] * omega;
00537 a[s] = fm * sn * sn + a[s] * cn * cn - a[u] * omega;
00538 a[u] = 0.0;
00539 a[t] = 0.0;
00540 for (j = 0; j <= n - 1; j++)
00541 {
00542 if ((j != p) && (j != q))
00543 {
00544 u = p * n + j;
00545 w = q * n + j;
00546 fm = a[u];
00547 a[u] = fm * cn + a[w] * sn;
00548 a[w] = -fm * sn + a[w] * cn;
00549 }
00550 }
00551 for (i = 0; i <= n - 1; i++)
00552 {
00553 if ((i != p) && (i != q))
00554 {
00555 u = i * n + p;
00556 w = i * n + q;
00557 fm = a[u];
00558 a[u] = fm * cn + a[w] * sn;
00559 a[w] = -fm * sn + a[w] * cn;
00560 }
00561 }
00562 for (i = 0; i <= n - 1; i++)
00563 {
00564 u = i * n + p;
00565 w = i * n + q;
00566 fm = v[u];
00567 v[u] = fm * cn + v[w] * sn;
00568 v[w] = -fm * sn + v[w] * cn;
00569 }
00570 }
00571 return 0;
00572 }
00573
00574 CPoint3d CSceneRecog::srNormalVec (CPoint3d start1, CPoint3d end1, CPoint3d start2, CPoint3d end2)
00575 {
00576 float r1, r2;
00577 CPoint3d point1, point2, point;
00578 point1 = srVecMuti (start1, end1, start1, end2);
00579 point2 = srVecMuti (start2, end1, start2, end2);
00580 r1 = sqrt (point1.x * point1.x + point1.y * point1.y + point1.z * point1.z);
00581 r2 = sqrt (point2.x * point2.x + point2.y * point2.y + point2.z * point2.z);
00582 point.x = (point1.x / r1 + point2.x / r2) / 2;
00583 point.y = (point1.y / r1 + point2.y / r2) / 2;
00584 point.z = (point1.z / r1 + point2.z / r2) / 2;
00585 return point;
00586 }
00587
00588 CPoint3d CSceneRecog::srVecMuti (CPoint3d start1, CPoint3d end1, CPoint3d start2, CPoint3d end2)
00589 {
00590 float x1, y1, z1;
00591 float x2, y2, z2;
00592 x1 = end1.x - start1.x;
00593 y1 = end1.y - start1.y;
00594 z1 = end1.z - start1.z;
00595 x2 = end2.x - start2.x;
00596 y2 = end2.y - start2.y;
00597 z2 = end2.z - start2.z;
00598 CPoint3d point;
00599 point.x = y1 * z2 - y2 * z1;
00600 point.y = x2 * z1 - x1 * z2;
00601 point.z = x1 * y2 - x2 * y1;
00602
00603 return point;
00604 }
00605
00606 float CSceneRecog::srAngle (CPoint3d vec1, CPoint3d vec2)
00607 {
00608 float x1, y1, z1, p1, p2, result, theta;
00609 x1 = vec1.x * vec2.x;
00610 y1 = vec1.y * vec2.y;
00611 z1 = vec1.z * vec2.z;
00612 p1 = vec1.x * vec1.x + vec1.y * vec1.y + vec1.z * vec1.z;
00613 p2 = vec2.x * vec2.x + vec2.y * vec2.y + vec2.z * vec2.z;
00614 result = (x1 + y1 + z1) / sqrt (p1 * p2);
00615 theta = acos (result);
00616
00617 return theta;
00618 }
00619
00620 float CSceneRecog::srP2Pl (CPoint3d m, const Plane & Plane)
00621 {
00622 float dist;
00623 dist = fabs (Plane.A * m.x + Plane.B * m.y + Plane.C * m.z + Plane.D);
00624 dist = dist / sqrt (Plane.A * Plane.A + Plane.B * Plane.B + Plane.C * Plane.C);
00625
00626 return dist;
00627 }
00628
00629 void CSceneRecog::srCalColor (int idx, std::vector < float >&rgb)
00630 {
00631 static int preidx = 1000;
00632 float step = 1;
00633 if (idx < 0)
00634 {
00635 rgb[0] = 0.5;
00636 rgb[1] = 0.5;
00637 rgb[2] = 0.5;
00638 }
00639 else if (idx != preidx)
00640 {
00641 float ratio = idx % 8;
00642 ratio = (1 - ratio / 8);
00643 switch (idx % 6)
00644 {
00645 case 0:
00646 rgb[0] = ratio * step;
00647 rgb[1] = 0;
00648 rgb[2] = 0;
00649 break;
00650 case 1:
00651 rgb[0] = 0;
00652 rgb[1] = ratio * step;
00653 rgb[2] = 0;
00654 break;
00655 case 2:
00656 rgb[0] = 0;
00657 rgb[1] = 0;
00658 rgb[2] = ratio * step;
00659 break;
00660 case 3:
00661 rgb[0] = ratio * step;
00662 rgb[1] = ratio * step;
00663 rgb[2] = 0;
00664 break;
00665 case 4:
00666 rgb[0] = ratio * step;
00667 rgb[1] = 0;
00668 rgb[2] = ratio * step;
00669 break;
00670 case 5:
00671 rgb[0] = 0;
00672 rgb[1] = ratio * step;
00673 rgb[2] = ratio * step;
00674 break;
00675 }
00676 }
00677 preidx = idx;
00678 }
00679
00680 bool CSceneRecog::srCompL1R0bool (const CPointIndex & p1, const CPointIndex & p2, const CPointIndex & p3)
00681 {
00682 bool res = 1;
00683 int temp = (p2.j - p1.j) * (p3.i - p1.i) - (p2.i - p1.i) * (p3.j - p1.j);
00684 if (temp < 0)
00685 {
00686 res = 0;
00687 }
00688 else if (temp == 0)
00689 {
00690 int dist1 = (p2.i - p1.i) * (p2.i - p1.i) + (p2.j - p1.j) * (p2.j - p1.j);
00691 int dist2 = (p3.i - p1.i) * (p3.i - p1.i) + (p3.j - p1.j) * (p3.j - p1.j);
00692 if (dist1 > dist2)
00693 res = 0;
00694 }
00695
00696 return res;
00697 }
00698
00699 inline int CSceneRecog::srCross_Product (const CPointIndex & p1, const CPointIndex & p2, const CPointIndex & p3)
00700 {
00701 return (p2.j - p1.j) * (p3.i - p1.i) - (p2.i - p1.i) * (p3.j - p1.j);
00702 }