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
00033 #include <srs_env_model_percp/but_segmentation/normals.h>
00034
00035
00036 #include <stdlib.h>
00037 #include <stdio.h>
00038 #include <time.h>
00039
00040
00041 #include <Eigen/Core>
00042 #include <Eigen/Eigenvalues>
00043
00044
00045 #include <opencv2/imgproc/imgproc.hpp>
00046
00047
00048 #include <pcl/point_cloud.h>
00049 #include <pcl/point_types.h>
00050 #include <pcl/features/integral_image_normal.h>
00051
00052 using namespace sensor_msgs;
00053 using namespace std;
00054 using namespace cv;
00055
00056
00057 namespace but_plane_detector
00058 {
00059
00061
00062
00063
00064
00065
00066
00067
00068
00069
00071 Normals::Normals(cv::Mat &points, const CameraInfoConstPtr& cam_info, int normalType, int neighborhood, float threshold, float outlierThreshold, int iter):
00072 m_points(points.size(), CV_32FC3),
00073 m_planes(points.size(), CV_32FC4)
00074 {
00075
00076 m_cam_info = (CameraInfoConstPtr)cam_info;
00077
00078 float aux;
00079 Vec3f nullvector(0.0, 0.0, 0.0);
00080 Vec4f nullvector4(0.0, 0.0, 0.0, 0.0);
00081
00082 if (normalType == NormalType::PCL)
00083 {
00084 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>());
00085
00086
00087 cloud->width = points.cols;
00088 cloud->height = points.rows;
00089 cloud->points.resize (cloud->width * cloud->height);
00090
00091 for (int i = 0; i < points.rows; ++i)
00092 for (int j = 0; j < points.cols; ++j)
00093 {
00094
00095
00096
00097 if ((aux = points.at<unsigned short>(i, j)) != 0)
00098 {
00099 Vec3f realPoint;
00100 realPoint[2] = aux/1000.0;
00101 realPoint[0] = ( (j - cam_info->K[2]) * realPoint[2] / cam_info->K[0] );
00102 realPoint[1] = ( (i - cam_info->K[5]) * realPoint[2] / cam_info->K[4] );
00103 cloud->operator()(j, i).x = realPoint[0];
00104 cloud->operator()(j, i).y = realPoint[1];
00105 cloud->operator()(j, i).z = realPoint[2];
00106
00107 m_points.at<Vec3f>(i, j) = realPoint;
00108 }
00109 else
00110 {
00111 m_points.at<Vec3f>(i, j) = nullvector;
00112 cloud->operator()(j, i).x = 0.0;
00113 cloud->operator()(j, i).y = 0.0;
00114 cloud->operator()(j, i).z = 0.0;
00115 }
00116 }
00117
00118
00119 pcl::IntegralImageNormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
00120
00121 pcl::PointCloud<pcl::Normal> normals;
00122
00123 ne.setNormalEstimationMethod (ne.AVERAGE_DEPTH_CHANGE);
00124 ne.setDepthDependentSmoothing(true);
00125 ne.setMaxDepthChangeFactor(threshold);
00126
00127 ne.setNormalSmoothingSize((float)(neighborhood*2+1));
00128 ne.setInputCloud(cloud);
00129 ne.compute(normals);
00130
00131 #pragma omp parallel for
00132 for (int i = 0; i < points.rows; ++i)
00133 for (int j = 0; j < points.cols; ++j)
00134 {
00135 Vec3f realPoint = m_points.at<Vec3f>(i, j);
00136 if (realPoint != nullvector)
00137 {
00138 Vec4f normal;
00139 if (normals(j, i).normal_x == normals(j, i).normal_x)
00140 {
00141 normal[0] = normals(j, i).normal_x;
00142 normal[1] = normals(j, i).normal_y;
00143 normal[2] = normals(j, i).normal_z;
00144 if (normal[2] < 0)
00145 {
00146 normal[0] *= -1.0;
00147 normal[1] *= -1.0;
00148 normal[2] *= -1.0;
00149 }
00150 normal[3] = -(normal[0]*realPoint[0]+normal[1]*realPoint[1]+normal[2]*realPoint[2]);
00151 m_planes.at<Vec4f>(i, j) = normal;
00152 }
00153 else
00154 m_planes.at<Vec4f>(i, j) = nullvector4;
00155 }
00156 else
00157 {
00158 m_planes.at<Vec4f>(i, j) = nullvector4;
00159 }
00160 }
00161 }
00162 else
00163 {
00164 for (int i = 0; i < points.rows; ++i)
00165 for (int j = 0; j < points.cols; ++j)
00166 {
00167 if ((aux = points.at<unsigned short>(i, j)) != 0)
00168 {
00169 Vec3f realPoint;
00170 realPoint[2] = aux/1000.0;
00171 realPoint[0] = ( (j - cam_info->K[2]) * realPoint[2] / cam_info->K[0] );
00172 realPoint[1] = ( (i - cam_info->K[5]) * realPoint[2] / cam_info->K[4] );
00173 m_points.at<Vec3f>(i, j) = realPoint;
00174 }
00175 else
00176 {
00177 m_points.at<Vec3f>(i, j) = nullvector;
00178 }
00179 }
00180
00181 if (normalType & NormalType::DIRECT)
00182 {
00183 for (int i = 0; i < points.rows; ++i)
00184 for (int j = 0; j < points.cols; ++j)
00185 {
00186 Vec3f realPoint = m_points.at<Vec3f>(i, j);
00187 if (realPoint != nullvector)
00188 {
00189 Vec4f normal = getNormal(i, j, neighborhood, threshold);
00190 m_planes.at<Vec4f>(i, j) = normal;
00191 }
00192 else
00193 {
00194 m_planes.at<Vec4f>(i, j) = nullvector4;
00195 }
00196 }
00197 }
00198 else if (normalType & NormalType::LSQ)
00199 {
00200 for (int i = 0; i < points.rows; ++i)
00201 for (int j = 0; j < points.cols; ++j)
00202 {
00203 Vec3f realPoint = m_points.at<Vec3f>(i, j);
00204 if (realPoint != nullvector)
00205 {
00206 Vec4f normal = getNormalLSQ(i, j, neighborhood, threshold);
00207 m_planes.at<Vec4f>(i, j) = normal;
00208 }
00209 else
00210 {
00211 m_planes.at<Vec4f>(i, j) = nullvector4;
00212 }
00213 }
00214 }
00215 else if (normalType & NormalType::LSQAROUND)
00216 {
00217 #pragma omp parallel for
00218 for (int i = 0; i < points.rows; ++i)
00219 for (int j = 0; j < points.cols; ++j)
00220 {
00221 Vec3f realPoint = m_points.at<Vec3f>(i, j);
00222 if (realPoint != nullvector)
00223 {
00224 Vec4f normal= getNormalLSQAround(i, j, neighborhood, threshold);
00225 m_planes.at<Vec4f>(i, j) = normal;
00226 }
00227 else
00228 m_planes.at<Vec4f>(i, j) = nullvector4;
00229 }
00230 }
00231 else if (normalType & NormalType::LTS)
00232 {
00233 for (int i = 0; i < points.rows; ++i)
00234 for (int j = 0; j < points.cols; ++j)
00235 {
00236 Vec3f realPoint = m_points.at<Vec3f>(i, j);
00237 if (realPoint != nullvector)
00238 {
00239 Vec4f normal = getNormalLTS(i, j, neighborhood, threshold, outlierThreshold, iter);
00240 m_planes.at<Vec4f>(i, j) = normal;
00241 }
00242 else
00243 {
00244 m_planes.at<Vec4f>(i, j) = nullvector4;
00245 }
00246 }
00247 }
00248 else if (normalType & NormalType::LTSAROUND)
00249 {
00250 for (int i = 0; i < points.rows; ++i)
00251 for (int j = 0; j < points.cols; ++j)
00252 {
00253 Vec3f realPoint = m_points.at<Vec3f>(i, j);
00254 if (realPoint != nullvector)
00255 {
00256 Vec4f normal = getNormalLTSAround(i, j, neighborhood, threshold, outlierThreshold, iter);
00257 m_planes.at<Vec4f>(i, j) = normal;
00258 }
00259 else
00260 {
00261 m_planes.at<Vec4f>(i, j) = nullvector4;
00262 }
00263 }
00264 }
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274 }
00275
00277
00278
00279
00280
00282 Normals::Normals(pcl::PointCloud<pcl::PointXYZ> &pointcloud, int normalType, int neighborhood,
00283 float threshold, float outlierThreshold, int iter):
00284 m_points(cvSize(pointcloud.width, pointcloud.height), CV_32FC3),
00285 m_planes(cvSize(pointcloud.width, pointcloud.height), CV_32FC4)
00286 {
00287 std::cerr << "Normal computation method " << normalType << std::endl;
00288
00289 Vec3f nullvector(0.0, 0.0, 0.0);
00290 Vec4f nullvector4(0.0, 0.0, 0.0, 0.0);
00291
00292 for(int y = 0; y < (int)pointcloud.height; ++y)
00293 for(int x = 0; x < (int)pointcloud.width; ++x)
00294 {
00295 Vec3f realPoint;
00296 realPoint[0] = pointcloud.at(x, y).x;
00297 realPoint[1] = pointcloud.at(x, y).y;
00298 realPoint[2] = pointcloud.at(x, y).z;
00299
00300 m_points.at<Vec3f>(y, x) = realPoint;
00301 }
00302
00303 if (normalType == NormalType::PCL)
00304 {
00305
00306 pcl::IntegralImageNormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
00307 pcl::PointCloud<pcl::Normal> normals;
00308
00309 ne.setNormalEstimationMethod (ne.COVARIANCE_MATRIX);
00310 ne.setDepthDependentSmoothing(true);
00311 ne.setMaxDepthChangeFactor(threshold);
00312 ne.setNormalSmoothingSize(neighborhood);
00313 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = pointcloud.makeShared();
00314 ne.setInputCloud(cloud);
00315 ne.compute(normals);
00316
00317 for (int i = 0; i < m_points.rows; ++i)
00318 for (int j = 0; j < m_points.cols; ++j)
00319 {
00320 Vec3f realPoint = m_points.at<Vec3f>(i, j);
00321
00322 Vec4f normal;
00323 if (normals(j, i).normal_x == normals(j, i).normal_x &&
00324 normals(j, i).normal_y == normals(j, i).normal_y &&
00325 normals(j, i).normal_z == normals(j, i).normal_z)
00326 {
00327 normal[0] = normals(j, i).normal_x;
00328 normal[1] = normals(j, i).normal_y;
00329 normal[2] = normals(j, i).normal_z;
00330
00331 normal[3] = -(normal[0]*realPoint[0]+normal[1]*realPoint[1]+normal[2]*realPoint[2]);
00332 m_planes.at<Vec4f>(i, j) = normal;
00333 }
00334 else
00335 m_planes.at<Vec4f>(i, j) = nullvector4;
00336 }
00337 }
00338 else if (normalType == NormalType::LSQAROUND)
00339 {
00340 for (int i = 0; i < m_points.rows; ++i)
00341 for (int j = 0; j < m_points.cols; ++j)
00342 {
00343 Vec3f realPoint = m_points.at<Vec3f>(i, j);
00344 if (realPoint != nullvector)
00345 {
00346 Vec4f normal= getNormalLSQAround(i, j, neighborhood, threshold);
00347 m_planes.at<Vec4f>(i, j) = normal;
00348 }
00349 else
00350 m_planes.at<Vec4f>(i, j) = nullvector4;
00351 }
00352 }
00353
00354 else if (normalType & NormalType::DIRECT)
00355 {
00356 for (int i = 0; i < m_points.rows; ++i)
00357 for (int j = 0; j < m_points.cols; ++j)
00358 {
00359 Vec3f realPoint = m_points.at<Vec3f>(i, j);
00360 if (realPoint != nullvector)
00361 {
00362 Vec4f normal = getNormal(i, j, neighborhood, threshold);
00363 m_planes.at<Vec4f>(i, j) = normal;
00364 }
00365 else
00366 {
00367 m_planes.at<Vec4f>(i, j) = nullvector4;
00368 }
00369 }
00370 }
00371 else if (normalType & NormalType::LSQ)
00372 {
00373 for (int i = 0; i < m_points.rows; ++i)
00374 for (int j = 0; j < m_points.cols; ++j)
00375 {
00376 Vec3f realPoint = m_points.at<Vec3f>(i, j);
00377 if (realPoint != nullvector)
00378 {
00379 Vec4f normal = getNormalLSQ(i, j, neighborhood, threshold);
00380 m_planes.at<Vec4f>(i, j) = normal;
00381 }
00382 else
00383 {
00384 m_planes.at<Vec4f>(i, j) = nullvector4;
00385 }
00386 }
00387 }
00388
00389 else if (normalType & NormalType::LTS)
00390 {
00391 for (int i = 0; i < m_points.rows; ++i)
00392 for (int j = 0; j < m_points.cols; ++j)
00393 {
00394 Vec3f realPoint = m_points.at<Vec3f>(i, j);
00395 if (realPoint != nullvector)
00396 {
00397 Vec4f normal = getNormalLTS(i, j, neighborhood, threshold, outlierThreshold, iter);
00398 m_planes.at<Vec4f>(i, j) = normal;
00399 }
00400 else
00401 {
00402 m_planes.at<Vec4f>(i, j) = nullvector4;
00403 }
00404 }
00405 }
00406 else if (normalType & NormalType::LTSAROUND)
00407 {
00408 for (int i = 0; i < m_points.rows; ++i)
00409 for (int j = 0; j < m_points.cols; ++j)
00410 {
00411 Vec3f realPoint = m_points.at<Vec3f>(i, j);
00412 if (realPoint != nullvector)
00413 {
00414 Vec4f normal = getNormalLTSAround(i, j, neighborhood, threshold, outlierThreshold, iter);
00415 m_planes.at<Vec4f>(i, j) = normal;
00416 }
00417 else
00418 {
00419 m_planes.at<Vec4f>(i, j) = nullvector4;
00420 }
00421 }
00422 }
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 }
00438
00439
00440
00441
00442
00444 cv::Vec4f Normals::getNormal(int i, int j, int step, float depthThreshold)
00445 {
00446 int size = (step*2)*4;
00447
00448 cv::Vec<float, 4> normalVec;
00449 normalVec[0] = 0;
00450 normalVec[1] = 0;
00451 normalVec[2] = 0;
00452 normalVec[3] = 0;
00453
00454 if (i < step || j < step || i >= m_points.rows-step || j >= m_points.cols-step)
00455 return normalVec;
00456
00457 cv::Vec3f aux;
00458 cv::Vec3f center;
00459
00460 Vec3f realPoint = m_points.at<Vec3f>(i, j);
00461 center[0] = realPoint[0];
00462 center[1] = realPoint[1];
00463 center[2] = realPoint[2];
00464
00465 std::vector<Vec3f> around;
00466
00467
00468
00469 int x = -step;
00470 int y = -step;
00471 int plusX = 1;
00472 int plusY = 0;
00473
00474 Vec3f centroid;
00475 centroid[0] = 0;
00476 centroid[1] = 0;
00477 centroid[2] = 0;
00478
00479 for (int index = 0; index < size; ++index)
00480 {
00481 realPoint = m_points.at<Vec3f>(i+x, j+y);
00482 if (abs(center[2]-realPoint[2]) < depthThreshold)
00483 {
00484 centroid += realPoint;
00485 around.push_back(realPoint - center);
00486 }
00487
00488
00489 nextStep(step, x, y, plusX, plusY);
00490
00491 }
00492 size = around.size();
00493 centroid[0] /= size;
00494 centroid[1] /= size;
00495 centroid[2] /= size;
00496
00497 for (int index = 0; index < size; ++index)
00498 {
00499 int second = ((index+1) % size);
00500 aux = around[index].cross(around[second]);
00501 normalVec = normalVec + Vec4f(aux[0], aux[1], aux[2], 0.0);
00502 }
00503
00504 normalVec[3] = -(centroid[0]*normalVec[0] + centroid[1]*normalVec[1] + centroid[2]*normalVec[2]);
00505
00506 float norm = sqrt(normalVec[0]*normalVec[0] + normalVec[1]*normalVec[1] + normalVec[2]*normalVec[2]);
00507 if (norm != 0)
00508 {
00509 if (normalVec[2] < 0)
00510 {
00511 normalVec[0] = normalVec[0] / -norm;
00512 normalVec[1] = normalVec[1] / -norm;
00513 normalVec[2] = normalVec[2] / -norm;
00514 normalVec[3] = normalVec[3] / -norm;
00515 }
00516 else
00517 {
00518 normalVec[0] = normalVec[0] / norm;
00519 normalVec[1] = normalVec[1] / norm;
00520 normalVec[2] = normalVec[2] / norm;
00521 normalVec[3] = normalVec[3] / norm;
00522 }
00523 }
00524
00525 return normalVec;
00526 }
00527
00529
00530
00531
00532
00533
00535 cv::Vec4f Normals::getNormalLSQ(int i, int j, int step, float depthThreshold)
00536 {
00537 cv::Vec<float, 4> normalVec;
00538 normalVec[0] = 0;
00539 normalVec[1] = 0;
00540 normalVec[2] = 0;
00541 normalVec[3] = 0;
00542
00543 if (i < step || j < step || i >= m_points.rows-step || j >= m_points.cols-step)
00544 return normalVec;
00545
00546 int iMax = i+step;
00547 int jMax = j+step;
00548
00549 std::vector<Vec3f> points;
00550
00551 Vec3f center = m_points.at<Vec3f>(i, j);
00552 Vec3f point;
00553 for (int x = i-step; x <= iMax; ++x)
00554 for (int y = j-step; y <= jMax; ++y)
00555 {
00556 point = m_points.at<Vec3f>(x, y);
00557 if (abs(center[2]-point[2]) < depthThreshold)
00558 {
00559 points.push_back(point);
00560 }
00561 }
00562
00563 if (points.size() < 3)
00564 return normalVec;
00565
00566 Plane<float> plane = LeastSquaresPlane(points);
00567
00568 return Vec4f(plane.a, plane.b, plane.c, plane.d);
00569 }
00570
00572
00573
00574
00575
00576
00578 cv::Vec4f Normals::getNormalLSQAround(int i, int j, int step, float depthThreshold)
00579 {
00580 cv::Vec<float, 4> normalVec;
00581 normalVec[0] = 0;
00582 normalVec[1] = 0;
00583 normalVec[2] = 0;
00584 normalVec[3] = 0;
00585
00586 if (i < step || j < step || i >= m_points.rows-step || j >= m_points.cols-step)
00587 return normalVec;
00588
00589 std::vector<Vec3f> points;
00590
00591 Vec3f center = m_points.at<Vec3f>(i, j);
00592 Vec3f point;
00593 int x = -step;
00594 int y = -step;
00595 int plusX = 1;
00596 int plusY = 0;
00597 int size = (step*2)*4;
00598
00599 for (int index = 0; index < size; ++index)
00600 {
00601 point = m_points.at<Vec3f>(i+x, j+y);
00602 if (abs(center[2]-point[2]) < depthThreshold)
00603 {
00604 points.push_back(point);
00605 }
00606
00607
00608 nextStep(step, x, y, plusX, plusY);
00609
00610 }
00611
00612 if (points.size() < 3)
00613 return normalVec;
00614
00615 Plane<float> plane = LeastSquaresPlane(points);
00616
00617 return Vec4f(plane.a, plane.b, plane.c, plane.d);
00618 }
00619
00621
00622
00623
00624
00625
00626
00627
00629 cv::Vec4f Normals::getNormalLTS(int i, int j, int step, float depthThreshold, float outlierThreshold, int maxIter)
00630 {
00631 cv::Vec<float, 4> normalVec;
00632 normalVec[0] = 0;
00633 normalVec[1] = 0;
00634 normalVec[2] = 0;
00635 normalVec[3] = 0;
00636
00637 if (i < step || j < step || i >= m_points.rows-step || j >= m_points.cols-step)
00638 return normalVec;
00639
00640 int iMax = i+step;
00641 int jMax = j+step;
00642
00643 Plane<float> best(0.0, 0.0, 0.0, 0.0);
00644 float bestScore = 9999999.0;
00645 Plane<float> candidate(0.0, 0.0, 0.0, 0.0);
00646 Vec3f center = m_points.at<Vec3f>(i, j);
00647 Vec3f point;
00648 for (int cnt = 0; cnt < maxIter; ++cnt)
00649 {
00650 std::vector<Vec3f> points;
00651 for (int x = i-step; x <= iMax; ++x)
00652 for (int y = j-step; y <= jMax; ++y)
00653 {
00654 point = m_points.at<Vec3f>(x, y);
00655 if (rand() > RAND_MAX/2 && abs(center[2]-point[2]) < depthThreshold)
00656 {
00657 points.push_back(point);
00658 }
00659 }
00660
00661 candidate = LeastSquaresPlane(points);
00662
00663 float score = 0.0;
00664 float count = 0.0;
00665 float aux;
00666
00667 for (int x = i-step; x < iMax; ++x)
00668 for (int y = j-step; y < jMax; ++y)
00669 {
00670 aux = candidate.distance(m_points.at<Vec3f>(x, y));
00671 if (aux < outlierThreshold)
00672 {
00673 score += aux;
00674 count += 1.0;
00675 }
00676 }
00677
00678 score /= count;
00679
00680 if (bestScore > score)
00681 {
00682 bestScore = score;
00683 best = candidate;
00684 }
00685 }
00686
00687 return Vec4f(best.a, best.b, best.c, best.d);
00688 }
00689
00691
00692
00693
00694
00695
00696
00697
00699 cv::Vec4f Normals::getNormalLTSAround(int i, int j, int step, float depthThreshold, float outlierThreshold, int maxIter)
00700 {
00701 cv::Vec<float, 4> normalVec;
00702 normalVec[0] = 0;
00703 normalVec[1] = 0;
00704 normalVec[2] = 0;
00705 normalVec[3] = 0;
00706
00707 if (i < step || j < step || i >= m_points.rows-step || j >= m_points.cols-step)
00708 return normalVec;
00709
00710 Plane<float> best(0.0, 0.0, 0.0, 0.0);
00711 float bestScore = 9999999.0;
00712 Plane<float> candidate(0.0, 0.0, 0.0, 0.0);
00713 Vec3f center = m_points.at<Vec3f>(i, j);
00714 Vec3f point;
00715 int size = (step*2)*4;
00716 for (int cnt = 0; cnt < maxIter; ++cnt)
00717 {
00718 std::vector<Vec3f> points;
00719
00720 int x = -step;
00721 int y = -step;
00722 int plusX = 1;
00723 int plusY = 0;
00724
00725 for (int index = 0; index < size; ++index)
00726 {
00727 point = m_points.at<Vec3f>(i+x, j+y);
00728 if (rand() > RAND_MAX/2 && abs(center[2]-point[2]) < depthThreshold)
00729 points.push_back(point);
00730
00731
00732 nextStep(step, x, y, plusX, plusY);
00733
00734 }
00735
00736 candidate = LeastSquaresPlane(points);
00737
00738 float score = 0.0;
00739 float count = 0.0;
00740 float aux;
00741
00742 x = -step;
00743 y = -step;
00744 plusX = 1;
00745 plusY = 0;
00746
00747 for (int index = 0; index < size; ++index)
00748 {
00749 aux = candidate.distance(m_points.at<Vec3f>(i+x, j+y));
00750 if (aux < outlierThreshold)
00751 {
00752 score += aux;
00753 count += 1.0;
00754 }
00755
00756 nextStep(step, x, y, plusX, plusY);
00757 }
00758
00759 score /= count;
00760
00761 if (bestScore > score)
00762 {
00763 bestScore = score;
00764 best = candidate;
00765 }
00766 }
00767
00768 return Vec4f(best.a, best.b, best.c, best.d);
00769 }
00770
00772
00773
00774
00775
00777 Plane<float> Normals::LeastSquaresPlane(std::vector<cv::Vec3f> &points)
00778 {
00779 if (points.size() == 0) return Plane<float>(0,0,0,0);
00780 cv::Vec3f centroid(0.0, 0.0, 0.0);
00781 Eigen::Matrix3f tensor = Eigen::Matrix3f::Zero();
00782
00784
00785 cv::Vec3f current = *points.begin();
00786 for (unsigned int i = 0; i < points.size(); ++i)
00787 centroid += points[i];
00788 centroid[0] /= points.size();
00789 centroid[1] /= points.size();
00790 centroid[2] /= points.size();
00791
00792
00794
00795 double dx, dy, dz;
00796 for (unsigned int i = 0; i < points.size(); ++i)
00797 {
00798 dx = centroid[0] - points[i][0];
00799 dy = centroid[1] - points[i][1];
00800 dz = centroid[2] - points[i][2];
00801
00802 tensor(0, 0) += dx*dx;
00803 tensor(0, 1) += dx*dy;
00804 tensor(0, 2) += dx*dz;
00805 tensor(1, 0) += dy*dx;
00806 tensor(1, 1) += dy*dy;
00807 tensor(1, 2) += dy*dz;
00808 tensor(2, 0) += dz*dx;
00809 tensor(2, 1) += dz*dy;
00810 tensor(2, 2) += dz*dz;
00811 }
00812
00814
00815 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> solver(tensor);
00816
00817 Eigen::Matrix3f eigenVectors;
00818 Eigen::Vector3f eigenValues;
00819
00820 eigenVectors = solver.eigenvectors();
00821 eigenValues = solver.eigenvalues();
00822 Plane<float> plane(eigenVectors(0, 0), eigenVectors(1, 0), eigenVectors(2, 0), -(centroid[0]*eigenVectors(0,0) + centroid[1]*eigenVectors(1,0) + centroid[2]*eigenVectors(2,0)));
00823
00825
00826 if (plane.norm != 0)
00827 {
00828 plane.a /= plane.norm;
00829 plane.b /= plane.norm;
00830 plane.c /= plane.norm;
00831 plane.d /= plane.norm;
00832 plane.norm = 1;
00833 }
00834 if (plane.c < 0)
00835 {
00836 plane.a *= -1.0;
00837 plane.b *= -1.0;
00838 plane.c *= -1.0;
00839 plane.d *= -1.0;
00840 }
00841
00842
00843 return plane;
00844 }
00845
00847
00848
00849
00850
00851
00852
00854 void Normals::nextStep(int step, int &x, int &y, int &plusX, int &plusY)
00855 {
00856 if (x == -step && y == -step)
00857 {
00858 plusX = 1;
00859 plusY = 0;
00860 }
00861 if (x == step && y == -step)
00862 {
00863 plusX = 0;
00864 plusY = 1;
00865 }
00866 if (x == step && y == step)
00867 {
00868 plusX = -1;
00869 plusY = 0;
00870 }
00871 if (x == -step && y == step)
00872 {
00873 plusX = 0;
00874 plusY = -1;
00875 }
00876 x += plusX;
00877 y += plusY;
00878 }
00879
00881
00882
00883
00885 void Normals::initQuantVectors(int n_bins, std::vector<cv::Vec3f> &vec)
00886 {
00887 float twoPI = (2.0 * M_PI);
00888
00889 float step = twoPI/n_bins;
00890 float sinPi4 = sin(M_PI_4);
00891 for (float i = 0; i < twoPI; i+= step)
00892 {
00893 vec.push_back(cv::Vec3f( cos(i)*sinPi4,
00894 sin(i)*sinPi4,
00895 sinPi4
00896 ));
00897 }
00898 }
00899
00901
00902
00903
00905 unsigned int Normals::getQuantVector(std::vector<cv::Vec3f> &vec, cv::Vec3f &vector)
00906 {
00907 unsigned int size = vec.size();
00908 unsigned int minimum = 10;
00909 float minimalVal = 9999.0;
00910 for (unsigned int i = 0; i < size; ++i)
00911 {
00912 float angle = acos( vec[i][0] * vector[0] +
00913 vec[i][1] * vector[1] +
00914 vec[i][2] * vector[2]);
00915 if (angle < minimalVal)
00916 {
00917 minimalVal = angle;
00918 minimum = i;
00919 }
00920 }
00921 return minimum;
00922
00923 }
00924
00925 }
00926