36 #include <visp3/core/vpCPUFeatures.h> 37 #include <visp3/mbt/vpMbtFaceDepthNormal.h> 38 #include <visp3/mbt/vpMbtTukeyEstimator.h> 41 #include <pcl/common/centroid.h> 42 #include <pcl/filters/extract_indices.h> 43 #include <pcl/segmentation/sac_segmentation.h> 46 #if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2) 47 #include <emmintrin.h> 48 #define VISP_HAVE_SSE2 1 51 #define USE_SSE_CODE 1 52 #if VISP_HAVE_SSE2 && USE_SSE_CODE 59 : m_cam(), m_clippingFlag(
vpPolygon3D::NO_CLIPPING), m_distFarClip(100), m_distNearClip(0.001), m_hiddenFace(NULL),
60 m_planeObject(), m_polygon(NULL), m_useScanLine(false), m_faceActivated(false),
61 m_faceCentroidMethod(GEOMETRIC_CENTROID), m_faceDesiredCentroid(), m_faceDesiredNormal(),
62 m_featureEstimationMethod(ROBUST_FEATURE_ESTIMATION), m_isTrackedDepthNormalFace(true), m_isVisible(false),
63 m_listOfFaceLines(), m_planeCamera(),
64 m_pclPlaneEstimationMethod(2),
65 m_pclPlaneEstimationRansacMaxIter(200), m_pclPlaneEstimationRansacThreshold(0.001), m_polygonLines()
93 PolygonLine polygon_line;
96 polygon_line.m_poly.setNbPoint(2);
97 polygon_line.m_poly.addPoint(0, P1);
98 polygon_line.m_poly.addPoint(1, P2);
104 polygon_line.m_p1 = &polygon_line.m_poly.p[0];
105 polygon_line.m_p2 = &polygon_line.m_poly.p[1];
110 bool already_here =
false;
152 const pcl::PointCloud<pcl::PointXYZ>::ConstPtr &point_cloud,
155 #
if DEBUG_DISPLAY_DEPTH_NORMAL
158 std::vector<std::vector<vpImagePoint> > &roiPts_vec
165 if (width == 0 || height == 0)
168 std::vector<vpImagePoint> roiPts;
172 #
if DEBUG_DISPLAY_DEPTH_NORMAL
178 if (roiPts.size() <= 2) {
180 std::cerr <<
"Error: roiPts.size() <= 2 in computeDesiredFeatures" << std::endl;
188 unsigned int top = (
unsigned int)std::max(0.0, bb.
getTop());
189 unsigned int bottom = (
unsigned int)std::min((
double)height, std::max(0.0, bb.
getBottom()));
190 unsigned int left = (
unsigned int)std::max(0.0, bb.
getLeft());
191 unsigned int right = (
unsigned int)std::min((
double)width, std::max(0.0, bb.
getRight()));
199 pcl::PointCloud<pcl::PointXYZ>::Ptr point_cloud_face(
new pcl::PointCloud<pcl::PointXYZ>);
200 std::vector<double> point_cloud_face_vec, point_cloud_face_custom;
216 double prev_x, prev_y, prev_z;
219 double x = 0.0, y = 0.0;
220 for (
unsigned int i = top; i < bottom; i += stepY) {
221 for (
unsigned int j = left; j < right; j += stepX) {
222 if (
vpMeTracker::inMask(mask, i, j) && pcl::isFinite((*point_cloud)(j, i)) && (*point_cloud)(j, i).z > 0 &&
223 (
m_useScanLine ? (i < m_hiddenFace->getMbScanLineRenderer().getPrimitiveIDs().getHeight() &&
224 j < m_hiddenFace->getMbScanLineRenderer().getPrimitiveIDs().getWidth() &&
229 point_cloud_face->push_back((*point_cloud)(j, i));
232 point_cloud_face_vec.push_back((*point_cloud)(j, i).x);
233 point_cloud_face_vec.push_back((*point_cloud)(j, i).y);
234 point_cloud_face_vec.push_back((*point_cloud)(j, i).z);
246 prev_z = (*point_cloud)(j, i).z;
249 point_cloud_face_custom.push_back(prev_x);
250 point_cloud_face_custom.push_back(x);
252 point_cloud_face_custom.push_back(prev_y);
253 point_cloud_face_custom.push_back(y);
255 point_cloud_face_custom.push_back(prev_z);
256 point_cloud_face_custom.push_back((*point_cloud)(j, i).z);
260 point_cloud_face_custom.push_back(x);
261 point_cloud_face_custom.push_back(y);
262 point_cloud_face_custom.push_back((*point_cloud)(j, i).z);
267 #if DEBUG_DISPLAY_DEPTH_NORMAL 268 debugImage[i][j] = 255;
275 if (checkSSE2 && push) {
276 point_cloud_face_custom.push_back(prev_x);
277 point_cloud_face_custom.push_back(prev_y);
278 point_cloud_face_custom.push_back(prev_z);
282 if (point_cloud_face->empty() && point_cloud_face_custom.empty() && point_cloud_face_vec.empty()) {
297 desired_normal, centroid_point);
312 const std::vector<vpColVector> &point_cloud,
315 #
if DEBUG_DISPLAY_DEPTH_NORMAL
318 std::vector<std::vector<vpImagePoint> > &roiPts_vec
325 if (width == 0 || height == 0)
328 std::vector<vpImagePoint> roiPts;
332 #
if DEBUG_DISPLAY_DEPTH_NORMAL
338 if (roiPts.size() <= 2) {
340 std::cerr <<
"Error: roiPts.size() <= 2 in computeDesiredFeatures" << std::endl;
348 unsigned int top = (
unsigned int)std::max(0.0, bb.
getTop());
349 unsigned int bottom = (
unsigned int)std::min((
double)height, std::max(0.0, bb.
getBottom()));
350 unsigned int left = (
unsigned int)std::max(0.0, bb.
getLeft());
351 unsigned int right = (
unsigned int)std::min((
double)width, std::max(0.0, bb.
getRight()));
359 std::vector<double> point_cloud_face, point_cloud_face_custom;
371 double prev_x, prev_y, prev_z;
374 double x = 0.0, y = 0.0;
375 for (
unsigned int i = top; i < bottom; i += stepY) {
376 for (
unsigned int j = left; j < right; j += stepX) {
378 (
m_useScanLine ? (i < m_hiddenFace->getMbScanLineRenderer().getPrimitiveIDs().getHeight() &&
379 j < m_hiddenFace->getMbScanLineRenderer().getPrimitiveIDs().getWidth() &&
383 point_cloud_face.push_back(point_cloud[i * width + j][0]);
384 point_cloud_face.push_back(point_cloud[i * width + j][1]);
385 point_cloud_face.push_back(point_cloud[i * width + j][2]);
397 prev_z = point_cloud[i * width + j][2];
400 point_cloud_face_custom.push_back(prev_x);
401 point_cloud_face_custom.push_back(x);
403 point_cloud_face_custom.push_back(prev_y);
404 point_cloud_face_custom.push_back(y);
406 point_cloud_face_custom.push_back(prev_z);
407 point_cloud_face_custom.push_back(point_cloud[i * width + j][2]);
411 point_cloud_face_custom.push_back(x);
412 point_cloud_face_custom.push_back(y);
413 point_cloud_face_custom.push_back(point_cloud[i * width + j][2]);
417 #if DEBUG_DISPLAY_DEPTH_NORMAL 418 debugImage[i][j] = 255;
425 if (checkSSE2 && push) {
426 point_cloud_face_custom.push_back(prev_x);
427 point_cloud_face_custom.push_back(prev_y);
428 point_cloud_face_custom.push_back(prev_z);
432 if (point_cloud_face.empty() && point_cloud_face_custom.empty()) {
441 pcl::PointCloud<pcl::PointXYZ>::Ptr point_cloud_face_pcl(
new pcl::PointCloud<pcl::PointXYZ>);
442 point_cloud_face_pcl->reserve(point_cloud_face.size() / 3);
444 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
445 point_cloud_face_pcl->push_back(
446 pcl::PointXYZ(point_cloud_face[3 * i], point_cloud_face[3 * i + 1], point_cloud_face[3 * i + 2]));
456 desired_normal, centroid_point);
475 pcl::ModelCoefficients::Ptr coefficients(
new pcl::ModelCoefficients);
476 pcl::PointIndices::Ptr inliers(
new pcl::PointIndices);
478 pcl::SACSegmentation<pcl::PointXYZ> seg;
480 seg.setOptimizeCoefficients(
true);
482 seg.setModelType(pcl::SACMODEL_PLANE);
487 seg.setInputCloud(point_cloud_face);
488 seg.segment(*inliers, *coefficients);
490 pcl::PointCloud<pcl::PointXYZ>::Ptr point_cloud_face_extracted(
new pcl::PointCloud<pcl::PointXYZ>);
492 pcl::ExtractIndices<pcl::PointXYZ> extract;
495 extract.setInputCloud(point_cloud_face);
496 extract.setIndices(inliers);
497 extract.setNegative(
false);
498 extract.filter(*point_cloud_face_extracted);
500 #if PCL_VERSION_COMPARE(>=, 1, 8, 0) 501 pcl::PointXYZ centroid_point_pcl;
502 if (pcl::computeCentroid(*point_cloud_face_extracted, centroid_point_pcl)) {
503 pcl::PointXYZ face_normal;
505 centroid_point_pcl, face_normal);
507 desired_features.
resize(3,
false);
508 desired_features[0] = -coefficients->values[0] / coefficients->values[3];
509 desired_features[1] = -coefficients->values[1] / coefficients->values[3];
510 desired_features[2] = -coefficients->values[2] / coefficients->values[3];
512 desired_normal[0] = face_normal.x;
513 desired_normal[1] = face_normal.y;
514 desired_normal[2] = face_normal.z;
516 centroid_point[0] = centroid_point_pcl.x;
517 centroid_point[1] = centroid_point_pcl.y;
518 centroid_point[2] = centroid_point_pcl.z;
520 std::cerr <<
"Cannot compute centroid!" << std::endl;
524 std::cerr <<
"Cannot compute centroid using PCL " << PCL_VERSION_PRETTY <<
"!" << std::endl;
527 }
catch (
const pcl::PCLException &e) {
528 std::cerr <<
"Catch a PCL exception: " << e.what() << std::endl;
537 const std::vector<double> &point_cloud_face,
543 std::vector<double> weights;
548 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
549 centroid_point[0] += weights[i] * point_cloud_face[3 * i];
550 centroid_point[1] += weights[i] * point_cloud_face[3 * i + 1];
551 centroid_point[2] += weights[i] * point_cloud_face[3 * i + 2];
556 centroid_point[0] /= den;
557 centroid_point[1] /= den;
558 centroid_point[2] /= den;
571 desired_features.
resize(3,
false);
572 desired_features[0] = -plane_equation_SVD[0] / plane_equation_SVD[3];
573 desired_features[1] = -plane_equation_SVD[1] / plane_equation_SVD[3];
574 desired_features[2] = -plane_equation_SVD[2] / plane_equation_SVD[3];
586 centroid_cam[0] = centroid_point[0];
587 centroid_cam[1] = centroid_point[1];
588 centroid_cam[2] = centroid_point[2];
596 face_normal_cam[0] = desired_normal[0];
597 face_normal_cam[1] = desired_normal[1];
598 face_normal_cam[2] = desired_normal[2];
599 face_normal_cam[3] = 1;
607 if (points_.empty()) {
611 if (points_.size() < 2) {
612 centroid = points_[0];
616 std::vector<vpPoint> points = points_;
617 points.push_back(points_.front());
619 double A1 = 0.0, A2 = 0.0, c_x1 = 0.0, c_x2 = 0.0, c_y = 0.0, c_z = 0.0;
621 for (
size_t i = 0; i < points.size() - 1; i++) {
623 c_x1 += (points[i].get_X() + points[i + 1].get_X()) *
624 (points[i].get_X() * points[i + 1].get_Y() - points[i + 1].get_X() * points[i].get_Y());
625 c_y += (points[i].get_Y() + points[i + 1].get_Y()) *
626 (points[i].get_X() * points[i + 1].get_Y() - points[i + 1].get_X() * points[i].get_Y());
627 A1 += points[i].
get_X() * points[i + 1].get_Y() - points[i + 1].get_X() * points[i].get_Y();
630 c_x2 += (points[i].get_X() + points[i + 1].get_X()) *
631 (points[i].get_X() * points[i + 1].get_Z() - points[i + 1].get_X() * points[i].get_Z());
632 c_z += (points[i].get_Z() + points[i + 1].get_Z()) *
633 (points[i].get_X() * points[i + 1].get_Z() - points[i + 1].get_X() * points[i].get_Z());
634 A2 += points[i].get_X() * points[i + 1].get_Z() - points[i + 1].get_X() * points[i].get_Z();
643 centroid.
set_X(c_x1);
645 centroid.
set_X(c_x2);
655 unsigned int height, std::vector<vpImagePoint> &roiPts
656 #
if DEBUG_DISPLAY_DEPTH_NORMAL
658 std::vector<std::vector<vpImagePoint> > &roiPts_vec
667 it->m_p1->changeFrame(cMo);
668 it->m_p2->changeFrame(cMo);
672 it->m_poly.changeFrame(cMo);
673 it->m_poly.computePolygonClipped(
m_cam);
675 if (it->m_poly.polyClipped.size() == 2 &&
683 std::vector<std::pair<vpPoint, vpPoint> > linesLst;
687 for (
unsigned int i = 0; i < linesLst.size(); i++) {
688 linesLst[i].first.project();
689 linesLst[i].second.project();
697 roiPts.push_back(ip1);
698 roiPts.push_back(ip2);
700 #if DEBUG_DISPLAY_DEPTH_NORMAL 701 std::vector<vpImagePoint> roiPts_;
702 roiPts_.push_back(ip1);
703 roiPts_.push_back(ip2);
704 roiPts_vec.push_back(roiPts_);
713 #if DEBUG_DISPLAY_DEPTH_NORMAL 714 roiPts_vec.push_back(roiPts);
728 bool isvisible =
false;
732 int index = *itindex;
765 std::vector<vpImagePoint> roiPts;
768 std::vector<vpPoint> polyPts;
776 e4[0] = -centroid.
get_X();
777 e4[1] = -centroid.
get_Y();
778 e4[2] = -centroid.
get_Z();
781 double centroid_x = 0.0;
782 double centroid_y = 0.0;
783 double centroid_z = 0.0;
785 for (
size_t i = 0; i < polyPts.size(); i++) {
786 centroid_x += polyPts[i].get_X();
787 centroid_y += polyPts[i].get_Y();
788 centroid_z += polyPts[i].get_Z();
791 centroid_x /= polyPts.
size();
792 centroid_y /= polyPts.size();
793 centroid_z /= polyPts.size();
800 centroid.
set_X(centroid_x);
801 centroid.
set_Y(centroid_y);
802 centroid.
set_Z(centroid_z);
805 correct_normal.
resize(3,
false);
807 if (angle < M_PI_2) {
808 correct_normal = faceNormal;
810 correct_normal[0] = -faceNormal[0];
811 correct_normal[1] = -faceNormal[1];
812 correct_normal[2] = -faceNormal[2];
818 const pcl::PointXYZ ¢roid_point, pcl::PointXYZ &face_normal)
827 e4[0] = -centroid_point.x;
828 e4[1] = -centroid_point.y;
829 e4[2] = -centroid_point.z;
833 if (angle < M_PI_2) {
834 face_normal = pcl::PointXYZ(faceNormal[0], faceNormal[1], faceNormal[2]);
836 face_normal = pcl::PointXYZ(-faceNormal[0], -faceNormal[1], -faceNormal[2]);
844 face_normal.
resize(3,
false);
854 if (angle >= M_PI_2) {
855 face_normal[0] = -face_normal[0];
856 face_normal[1] = -face_normal[1];
857 face_normal[2] = -face_normal[2];
863 L.
resize(3, 6,
false,
false);
876 features.
resize(3,
false);
877 features[0] = -ux / D;
878 features[1] = -uy / D;
879 features[2] = -uz / D;
882 L[0][0] = ux * ux / D2;
883 L[0][1] = ux * uy / D2;
884 L[0][2] = ux * uz / D2;
890 L[1][0] = ux * uy / D2;
891 L[1][1] = uy * uy / D2;
892 L[1][2] = uy * uz / D2;
898 L[2][0] = ux * uz / D2;
899 L[2][1] = uy * uz / D2;
900 L[2][2] = uz * uz / D2;
908 bool displayFullModel)
912 for (
size_t i = 0; i < models.size(); i++) {
921 bool displayFullModel)
925 for (
size_t i = 0; i < models.size(); i++) {
934 unsigned int thickness)
950 pt_extremity.
set_X(pt_centroid.
get_X() + pt_normal.get_X() * scale);
951 pt_extremity.
set_Y(pt_centroid.
get_Y() + pt_normal.get_Y() * scale);
952 pt_extremity.
set_Z(pt_centroid.
get_Z() + pt_normal.get_Z() * scale);
977 pt_extremity.
set_X(pt_centroid.
get_X() + correct_normal[0] * scale);
978 pt_extremity.
set_Y(pt_centroid.
get_Y() + correct_normal[1] * scale);
979 pt_extremity.
set_Z(pt_centroid.
get_Z() + correct_normal[2] * scale);
990 unsigned int thickness)
1003 pt_normal.project();
1006 pt_extremity.
set_X(pt_centroid.
get_X() + pt_normal.get_X() * scale);
1007 pt_extremity.
set_Y(pt_centroid.
get_Y() + pt_normal.get_Y() * scale);
1008 pt_extremity.
set_Z(pt_centroid.
get_Z() + pt_normal.get_Z() * scale);
1033 pt_extremity.
set_X(pt_centroid.
get_X() + correct_normal[0] * scale);
1034 pt_extremity.
set_Y(pt_centroid.
get_Y() + correct_normal[1] * scale);
1035 pt_extremity.
set_Z(pt_centroid.
get_Z() + correct_normal[2] * scale);
1047 vpMbtTukeyEstimator<double> tukey_robust;
1048 std::vector<double> residues(point_cloud_face.size() / 3);
1050 w.resize(point_cloud_face.size() / 3, 1.0);
1052 unsigned int max_iter = 30, iter = 0;
1053 double error = 0.0, prev_error = -1.0;
1054 double A = 0.0, B = 0.0, C = 0.0;
1056 Mat33<double> ATA_3x3;
1065 while (std::fabs(error - prev_error) > 1e-6 && (iter < max_iter)) {
1082 if (point_cloud_face.size() / 3 >= 2) {
1083 const double *ptr_point_cloud = &point_cloud_face[0];
1084 const __m128d vA = _mm_set1_pd(A);
1085 const __m128d vB = _mm_set1_pd(B);
1086 const __m128d vC = _mm_set1_pd(C);
1087 const __m128d vones = _mm_set1_pd(1.0);
1089 double *ptr_residues = &residues[0];
1091 for (; cpt <= point_cloud_face.size() - 6; cpt += 6, ptr_point_cloud += 6, ptr_residues += 2) {
1092 const __m128d vxi = _mm_loadu_pd(ptr_point_cloud);
1093 const __m128d vyi = _mm_loadu_pd(ptr_point_cloud + 2);
1094 const __m128d vZi = _mm_loadu_pd(ptr_point_cloud + 4);
1095 const __m128d vinvZi = _mm_div_pd(vones, vZi);
1098 _mm_add_pd(_mm_add_pd(_mm_mul_pd(vA, vxi), _mm_mul_pd(vB, vyi)), _mm_sub_pd(vC, vinvZi));
1099 _mm_storeu_pd(ptr_residues, tmp);
1103 for (; cpt < point_cloud_face.size(); cpt += 3) {
1104 double xi = point_cloud_face[cpt];
1105 double yi = point_cloud_face[cpt + 1];
1106 double Zi = point_cloud_face[cpt + 2];
1108 residues[cpt / 3] = (A * xi + B * yi + C - 1 / Zi);
1112 tukey_robust.MEstimator(residues, w, 1e-2);
1114 __m128d vsum_wi2_xi2 = _mm_setzero_pd();
1115 __m128d vsum_wi2_yi2 = _mm_setzero_pd();
1116 __m128d vsum_wi2 = _mm_setzero_pd();
1117 __m128d vsum_wi2_xi_yi = _mm_setzero_pd();
1118 __m128d vsum_wi2_xi = _mm_setzero_pd();
1119 __m128d vsum_wi2_yi = _mm_setzero_pd();
1121 __m128d vsum_wi2_xi_Zi = _mm_setzero_pd();
1122 __m128d vsum_wi2_yi_Zi = _mm_setzero_pd();
1123 __m128d vsum_wi2_Zi = _mm_setzero_pd();
1127 if (point_cloud_face.size() / 3 >= 2) {
1128 const double *ptr_point_cloud = &point_cloud_face[0];
1129 double *ptr_w = &w[0];
1131 const __m128d vones = _mm_set1_pd(1.0);
1133 for (; cpt <= point_cloud_face.size() - 6; cpt += 6, ptr_point_cloud += 6, ptr_w += 2) {
1134 const __m128d vwi2 = _mm_mul_pd(_mm_loadu_pd(ptr_w), _mm_loadu_pd(ptr_w));
1136 const __m128d vxi = _mm_loadu_pd(ptr_point_cloud);
1137 const __m128d vyi = _mm_loadu_pd(ptr_point_cloud + 2);
1138 const __m128d vZi = _mm_loadu_pd(ptr_point_cloud + 4);
1139 const __m128d vinvZi = _mm_div_pd(vones, vZi);
1141 vsum_wi2_xi2 = _mm_add_pd(vsum_wi2_xi2, _mm_mul_pd(vwi2, _mm_mul_pd(vxi, vxi)));
1142 vsum_wi2_yi2 = _mm_add_pd(vsum_wi2_yi2, _mm_mul_pd(vwi2, _mm_mul_pd(vyi, vyi)));
1143 vsum_wi2 = _mm_add_pd(vsum_wi2, vwi2);
1144 vsum_wi2_xi_yi = _mm_add_pd(vsum_wi2_xi_yi, _mm_mul_pd(vwi2, _mm_mul_pd(vxi, vyi)));
1145 vsum_wi2_xi = _mm_add_pd(vsum_wi2_xi, _mm_mul_pd(vwi2, vxi));
1146 vsum_wi2_yi = _mm_add_pd(vsum_wi2_yi, _mm_mul_pd(vwi2, vyi));
1148 const __m128d vwi2_invZi = _mm_mul_pd(vwi2, vinvZi);
1149 vsum_wi2_xi_Zi = _mm_add_pd(vsum_wi2_xi_Zi, _mm_mul_pd(vxi, vwi2_invZi));
1150 vsum_wi2_yi_Zi = _mm_add_pd(vsum_wi2_yi_Zi, _mm_mul_pd(vyi, vwi2_invZi));
1151 vsum_wi2_Zi = _mm_add_pd(vsum_wi2_Zi, vwi2_invZi);
1156 _mm_storeu_pd(vtmp, vsum_wi2_xi2);
1157 double sum_wi2_xi2 = vtmp[0] + vtmp[1];
1159 _mm_storeu_pd(vtmp, vsum_wi2_yi2);
1160 double sum_wi2_yi2 = vtmp[0] + vtmp[1];
1162 _mm_storeu_pd(vtmp, vsum_wi2);
1163 double sum_wi2 = vtmp[0] + vtmp[1];
1165 _mm_storeu_pd(vtmp, vsum_wi2_xi_yi);
1166 double sum_wi2_xi_yi = vtmp[0] + vtmp[1];
1168 _mm_storeu_pd(vtmp, vsum_wi2_xi);
1169 double sum_wi2_xi = vtmp[0] + vtmp[1];
1171 _mm_storeu_pd(vtmp, vsum_wi2_yi);
1172 double sum_wi2_yi = vtmp[0] + vtmp[1];
1174 _mm_storeu_pd(vtmp, vsum_wi2_xi_Zi);
1175 double sum_wi2_xi_Zi = vtmp[0] + vtmp[1];
1177 _mm_storeu_pd(vtmp, vsum_wi2_yi_Zi);
1178 double sum_wi2_yi_Zi = vtmp[0] + vtmp[1];
1180 _mm_storeu_pd(vtmp, vsum_wi2_Zi);
1181 double sum_wi2_Zi = vtmp[0] + vtmp[1];
1183 for (; cpt < point_cloud_face.size(); cpt += 3) {
1184 double wi2 = w[cpt / 3] * w[cpt / 3];
1186 double xi = point_cloud_face[cpt];
1187 double yi = point_cloud_face[cpt + 1];
1188 double Zi = point_cloud_face[cpt + 2];
1189 double invZi = 1.0 / Zi;
1191 sum_wi2_xi2 += wi2 * xi * xi;
1192 sum_wi2_yi2 += wi2 * yi * yi;
1194 sum_wi2_xi_yi += wi2 * xi * yi;
1195 sum_wi2_xi += wi2 * xi;
1196 sum_wi2_yi += wi2 * yi;
1198 sum_wi2_xi_Zi += wi2 * xi * invZi;
1199 sum_wi2_yi_Zi += wi2 * yi * invZi;
1200 sum_wi2_Zi += wi2 * invZi;
1203 ATA_3x3[0] = sum_wi2_xi2;
1204 ATA_3x3[1] = sum_wi2_xi_yi;
1205 ATA_3x3[2] = sum_wi2_xi;
1206 ATA_3x3[3] = sum_wi2_xi_yi;
1207 ATA_3x3[4] = sum_wi2_yi2;
1208 ATA_3x3[5] = sum_wi2_yi;
1209 ATA_3x3[6] = sum_wi2_xi;
1210 ATA_3x3[7] = sum_wi2_yi;
1211 ATA_3x3[8] = sum_wi2;
1213 Mat33<double> minv = ATA_3x3.inverse();
1215 A = minv[0] * sum_wi2_xi_Zi + minv[1] * sum_wi2_yi_Zi + minv[2] * sum_wi2_Zi;
1216 B = minv[3] * sum_wi2_xi_Zi + minv[4] * sum_wi2_yi_Zi + minv[5] * sum_wi2_Zi;
1217 C = minv[6] * sum_wi2_xi_Zi + minv[7] * sum_wi2_yi_Zi + minv[8] * sum_wi2_Zi;
1225 __m128d verror = _mm_set1_pd(0.0);
1226 if (point_cloud_face.size() / 3 >= 2) {
1227 const double *ptr_point_cloud = &point_cloud_face[0];
1228 const __m128d vA = _mm_set1_pd(A);
1229 const __m128d vB = _mm_set1_pd(B);
1230 const __m128d vC = _mm_set1_pd(C);
1231 const __m128d vones = _mm_set1_pd(1.0);
1233 double *ptr_residues = &residues[0];
1235 for (; cpt <= point_cloud_face.size() - 6; cpt += 6, ptr_point_cloud += 6, ptr_residues += 2) {
1236 const __m128d vxi = _mm_loadu_pd(ptr_point_cloud);
1237 const __m128d vyi = _mm_loadu_pd(ptr_point_cloud + 2);
1238 const __m128d vZi = _mm_loadu_pd(ptr_point_cloud + 4);
1239 const __m128d vinvZi = _mm_div_pd(vones, vZi);
1241 const __m128d tmp = _mm_add_pd(_mm_add_pd(_mm_mul_pd(vA, vxi), _mm_mul_pd(vB, vyi)), _mm_sub_pd(vC, vinvZi));
1242 verror = _mm_add_pd(verror, _mm_mul_pd(tmp, tmp));
1244 _mm_storeu_pd(ptr_residues, tmp);
1248 _mm_storeu_pd(vtmp, verror);
1249 error = vtmp[0] + vtmp[1];
1251 for (
size_t idx = cpt; idx < point_cloud_face.size(); idx += 3) {
1252 double xi = point_cloud_face[idx];
1253 double yi = point_cloud_face[idx + 1];
1254 double Zi = point_cloud_face[idx + 2];
1256 error +=
vpMath::sqr(A * xi + B * yi + C - 1 / Zi);
1257 residues[idx / 3] = (A * xi + B * yi + C - 1 / Zi);
1260 error /= point_cloud_face.size() / 3;
1266 while (std::fabs(error - prev_error) > 1e-6 && (iter < max_iter)) {
1282 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1283 double xi = point_cloud_face[3 * i];
1284 double yi = point_cloud_face[3 * i + 1];
1285 double Zi = point_cloud_face[3 * i + 2];
1287 residues[i] = (A * xi + B * yi + C - 1 / Zi);
1291 tukey_robust.MEstimator(residues, w, 1e-2);
1294 double sum_wi2_xi2 = 0.0, sum_wi2_yi2 = 0.0, sum_wi2 = 0.0;
1295 double sum_wi2_xi_yi = 0.0, sum_wi2_xi = 0.0, sum_wi2_yi = 0.0;
1297 double sum_wi2_xi_Zi = 0.0, sum_wi2_yi_Zi = 0.0, sum_wi2_Zi = 0.0;
1299 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1300 double wi2 = w[i] * w[i];
1302 double xi = point_cloud_face[3 * i];
1303 double yi = point_cloud_face[3 * i + 1];
1304 double Zi = point_cloud_face[3 * i + 2];
1305 double invZi = 1 / Zi;
1307 sum_wi2_xi2 += wi2 * xi * xi;
1308 sum_wi2_yi2 += wi2 * yi * yi;
1310 sum_wi2_xi_yi += wi2 * xi * yi;
1311 sum_wi2_xi += wi2 * xi;
1312 sum_wi2_yi += wi2 * yi;
1314 sum_wi2_xi_Zi += wi2 * xi * invZi;
1315 sum_wi2_yi_Zi += wi2 * yi * invZi;
1316 sum_wi2_Zi += wi2 * invZi;
1319 ATA_3x3[0] = sum_wi2_xi2;
1320 ATA_3x3[1] = sum_wi2_xi_yi;
1321 ATA_3x3[2] = sum_wi2_xi;
1322 ATA_3x3[3] = sum_wi2_xi_yi;
1323 ATA_3x3[4] = sum_wi2_yi2;
1324 ATA_3x3[5] = sum_wi2_yi;
1325 ATA_3x3[6] = sum_wi2_xi;
1326 ATA_3x3[7] = sum_wi2_yi;
1327 ATA_3x3[8] = sum_wi2;
1329 Mat33<double> minv = ATA_3x3.inverse();
1331 A = minv[0] * sum_wi2_xi_Zi + minv[1] * sum_wi2_yi_Zi + minv[2] * sum_wi2_Zi;
1332 B = minv[3] * sum_wi2_xi_Zi + minv[4] * sum_wi2_yi_Zi + minv[5] * sum_wi2_Zi;
1333 C = minv[6] * sum_wi2_xi_Zi + minv[7] * sum_wi2_yi_Zi + minv[8] * sum_wi2_Zi;
1339 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1340 double xi = point_cloud_face[3 * i];
1341 double yi = point_cloud_face[3 * i + 1];
1342 double Zi = point_cloud_face[3 * i + 2];
1344 error +=
vpMath::sqr(A * xi + B * yi + C - 1 / Zi);
1345 residues[i] = (A * xi + B * yi + C - 1 / Zi);
1348 error /= point_cloud_face.size() / 3;
1354 x_estimated.
resize(3,
false);
1364 unsigned int max_iter = 10;
1365 double prev_error = 1e3;
1366 double error = 1e3 - 1;
1368 std::vector<double> weights(point_cloud_face.size() / 3, 1.0);
1369 std::vector<double> residues(point_cloud_face.size() / 3);
1370 vpMatrix M((
unsigned int)(point_cloud_face.size() / 3), 3);
1371 vpMbtTukeyEstimator<double> tukey;
1374 for (
unsigned int iter = 0; iter < max_iter && std::fabs(error - prev_error) > 1e-6; iter++) {
1376 tukey.MEstimator(residues, weights, 1e-4);
1388 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1389 residues[i] = std::fabs(A * point_cloud_face[3 * i] + B * point_cloud_face[3 * i + 1] +
1390 C * point_cloud_face[3 * i + 2] + D) /
1391 sqrt(A * A + B * B + C * C);
1394 tukey.MEstimator(residues, weights, 1e-4);
1395 plane_equation_estimated.
resize(4,
false);
1399 double centroid_x = 0.0, centroid_y = 0.0, centroid_z = 0.0;
1400 double total_w = 0.0;
1402 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1403 centroid_x += weights[i] * point_cloud_face[3 * i];
1404 centroid_y += weights[i] * point_cloud_face[3 * i + 1];
1405 centroid_z += weights[i] * point_cloud_face[3 * i + 2];
1406 total_w += weights[i];
1409 centroid_x /= total_w;
1410 centroid_y /= total_w;
1411 centroid_z /= total_w;
1414 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1415 M[(
unsigned int)i][0] = weights[i] * (point_cloud_face[3 * i] - centroid_x);
1416 M[(
unsigned int)i][1] = weights[i] * (point_cloud_face[3 * i + 1] - centroid_y);
1417 M[(
unsigned int)i][2] = weights[i] * (point_cloud_face[3 * i + 2] - centroid_z);
1426 double smallestSv = W[0];
1427 unsigned int indexSmallestSv = 0;
1428 for (
unsigned int i = 1; i < W.
size(); i++) {
1429 if (W[i] < smallestSv) {
1431 indexSmallestSv = i;
1435 normal = V.
getCol(indexSmallestSv);
1438 double A = normal[0], B = normal[1], C = normal[2];
1439 double D = -(A * centroid_x + B * centroid_y + C * centroid_z);
1442 plane_equation_estimated[0] = A;
1443 plane_equation_estimated[1] = B;
1444 plane_equation_estimated[2] = C;
1445 plane_equation_estimated[3] = D;
1450 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1451 residues[i] = std::fabs(A * point_cloud_face[3 * i] + B * point_cloud_face[3 * i + 1] +
1452 C * point_cloud_face[3 * i + 2] + D) /
1453 sqrt(A * A + B * B + C * C);
1454 error += weights[i] * residues[i];
1460 tukey.MEstimator(residues, weights, 1e-4);
1463 centroid.
resize(3,
false);
1464 double total_w = 0.0;
1466 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1467 centroid[0] += weights[i] * point_cloud_face[3 * i];
1468 centroid[1] += weights[i] * point_cloud_face[3 * i + 1];
1469 centroid[2] += weights[i] * point_cloud_face[3 * i + 2];
1470 total_w += weights[i];
1473 centroid[0] /= total_w;
1474 centroid[1] /= total_w;
1475 centroid[2] /= total_w;
1478 double A = normal[0], B = normal[1], C = normal[2];
1479 double D = -(A * centroid[0] + B * centroid[1] + C * centroid[2]);
1482 plane_equation_estimated[0] = A;
1483 plane_equation_estimated[1] = B;
1484 plane_equation_estimated[2] = C;
1485 plane_equation_estimated[3] = D;
1497 std::vector<std::vector<double> > features;
1510 pt_normal.project();
1513 pt_extremity.
set_X(pt_centroid.
get_X() + pt_normal.get_X() * scale);
1514 pt_extremity.
set_Y(pt_centroid.
get_Y() + pt_normal.get_Y() * scale);
1515 pt_extremity.
set_Z(pt_centroid.
get_Z() + pt_normal.get_Z() * scale);
1522 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11) 1523 std::vector<double> params = {2,
1524 im_centroid.
get_i(),
1525 im_centroid.
get_j(),
1526 im_extremity.
get_i(),
1527 im_extremity.
get_j()};
1529 std::vector<double> params;
1530 params.push_back(2);
1531 params.push_back(im_centroid.
get_i());
1532 params.push_back(im_centroid.
get_j());
1533 params.push_back(im_extremity.
get_i());
1534 params.push_back(im_extremity.
get_j());
1536 features.push_back(params);
1554 pt_extremity.
set_X(pt_centroid.
get_X() + correct_normal[0] * scale);
1555 pt_extremity.
set_Y(pt_centroid.
get_Y() + correct_normal[1] * scale);
1556 pt_extremity.
set_Z(pt_centroid.
get_Z() + correct_normal[2] * scale);
1562 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11) 1563 std::vector<double> params = {3,
1564 im_centroid.
get_i(),
1565 im_centroid.
get_j(),
1566 im_extremity.
get_i(),
1567 im_extremity.
get_j()};
1569 std::vector<double> params;
1570 params.push_back(3);
1571 params.push_back(im_centroid.
get_i());
1572 params.push_back(im_centroid.
get_j());
1573 params.push_back(im_extremity.
get_i());
1574 params.push_back(im_extremity.
get_j());
1576 features.push_back(params);
1597 bool displayFullModel)
1599 std::vector<std::vector<double> > models;
1607 std::vector<std::vector<double> > lineModels = line->
getModelForDisplay(width, height, cMo, cam, displayFullModel);
1608 models.insert(models.end(), lineModels.begin(), lineModels.end());
1630 if (dx <= std::numeric_limits<double>::epsilon() && dy <= std::numeric_limits<double>::epsilon() &&
1631 dz <= std::numeric_limits<double>::epsilon())
1643 (*it)->setCameraParameters(camera);
1653 (*it)->useScanLine = v;
vpFeatureEstimationType m_featureEstimationMethod
Method to estimate the desired features.
void svd(vpColVector &w, vpMatrix &V)
Used to indicate that a value is not in the allowed range.
Implementation of a matrix and operations on matrices.
void getRoiClipped(const vpCameraParameters &cam, std::vector< vpImagePoint > &roi)
double get_oY() const
Get the point Y coordinate in the object frame.
Implements a 3D polygon with render functionnalities like clipping.
void computeVisibilityDisplay()
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
void setWorldCoordinates(double oX, double oY, double oZ)
void setVisible(bool _isvisible)
bool isVisible(unsigned int i)
Implementation of an homogeneous matrix and operations on such kind of matrices.
bool m_isTrackedDepthNormalFace
std::vector< std::vector< double > > getModelForDisplay(unsigned int width, unsigned int height, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, bool displayFullModel=false)
std::list< int > Lindex_polygon
Index of the faces which contain the line.
void setFarClippingDistance(const double &dist)
int m_pclPlaneEstimationMethod
PCL plane estimation method.
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
unsigned int m_clippingFlag
Flags specifying which clipping to used.
Class to define colors available for display functionnalities.
int m_pclPlaneEstimationRansacMaxIter
PCL pane estimation max number of iterations.
vpPoint * p1
The first extremity.
void computeDesiredFeaturesRobustFeatures(const std::vector< double > &point_cloud_face_custom, const std::vector< double > &point_cloud_face, const vpHomogeneousMatrix &cMo, vpColVector &desired_features, vpColVector &desired_normal, vpColVector ¢roid_point)
error that can be emited by ViSP classes.
vpMbScanLine & getMbScanLineRenderer()
vpHomogeneousMatrix inverse() const
Manage the line of a polygon used in the model-based tracker.
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
unsigned int size() const
Return the number of elements of the 2D array.
double m_distNearClip
Distance for near clipping.
void addLine(vpPoint &p1, vpPoint &p2, vpMbHiddenFaces< vpMbtPolygon > *const faces, int polygon=-1, std::string name="")
vpMbtPolygon & getPolygon()
void set_Y(double Y)
Set the point Y coordinate in the camera frame.
bool samePoint(const vpPoint &P1, const vpPoint &P2) const
void computeROI(const vpHomogeneousMatrix &cMo, unsigned int width, unsigned int height, std::vector< vpImagePoint > &roiPts)
double get_oX() const
Get the point X coordinate in the object frame.
bool m_useScanLine
Scan line visibility.
std::vector< std::vector< double > > getFeaturesForDisplay(const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, double scale=0.05)
vpCameraParameters m_cam
Camera intrinsic parameters.
vpRect getBoundingBox() const
Class that defines what is a point.
bool computePolygonCentroid(const std::vector< vpPoint > &points, vpPoint ¢roid)
void setCameraParameters(const vpCameraParameters &camera)
bool m_faceActivated
True if the face should be considered by the tracker.
vpMbtPolygon * m_polygon
Polygon defining the face.
Defines a generic 2D polygon.
void computeNormalVisibility(double nx, double ny, double nz, const vpColVector ¢roid_point, vpColVector &face_normal)
vpColVector & normalize()
std::vector< std::vector< double > > getModelForDisplay(unsigned int width, unsigned int height, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, bool displayFullModel=false)
void computeInteractionMatrix(const vpHomogeneousMatrix &cMo, vpMatrix &L, vpColVector &features)
void setScanLineVisibilityTest(bool v)
vpPoint * p2
The second extremity.
void changeFrame(const vpHomogeneousMatrix &cMo)
static void displayArrow(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color=vpColor::white, unsigned int w=4, unsigned int h=2, unsigned int thickness=1)
static double sqr(double x)
bool computeDesiredFeaturesPCL(const pcl::PointCloud< pcl::PointXYZ >::ConstPtr &point_cloud_face, vpColVector &desired_features, vpColVector &desired_normal, vpColVector ¢roid_point)
VISP_EXPORT bool checkSSE2()
bool isInside(const vpImagePoint &iP, const PointInPolygonMethod &method=PnPolyRayCasting) const
void getPolygonClipped(std::vector< std::pair< vpPoint, unsigned int > > &poly)
vpMbHiddenFaces< vpMbtPolygon > * m_hiddenFace
Pointer to the list of faces.
Generic class defining intrinsic camera parameters.
double get_oZ() const
Get the point Z coordinate in the object frame.
vpPoint m_faceDesiredNormal
Face (normalized) normal (computed from the sensor)
vpColVector getCol(unsigned int j) const
double m_distFarClip
Distance for near clipping.
virtual bool isVisible(const vpHomogeneousMatrix &cMo, double alpha, const bool &modulo=false, const vpCameraParameters &cam=vpCameraParameters(), unsigned int width=0, unsigned int height=0)
std::vector< vpMbtDistanceLine * > m_listOfFaceLines
void setClipping(const unsigned int &flags)
std::vector< PolygonLine > m_polygonLines
vpFaceCentroidType m_faceCentroidMethod
Method to compute the face centroid for the current features.
void setName(const std::string &line_name)
void setCameraParameters(const vpCameraParameters &camera)
void resize(unsigned int i, bool flagNullify=true)
double get_X() const
Get the point X coordinate in the camera frame.
void computeScanLineQuery(const vpPoint &a, const vpPoint &b, std::vector< std::pair< vpPoint, vpPoint > > &lines, const bool &displayResults=false)
void estimatePlaneEquationSVD(const std::vector< double > &point_cloud_face, const vpHomogeneousMatrix &cMo, vpColVector &plane_equation_estimated, vpColVector ¢roid)
unsigned int getHeight() const
void computeDesiredFeaturesSVD(const std::vector< double > &point_cloud_face, const vpHomogeneousMatrix &cMo, vpColVector &desired_features, vpColVector &desired_normal, vpColVector ¢roid_point)
void set_Z(double Z)
Set the point Z coordinate in the camera frame.
void computeDesiredNormalAndCentroid(const vpHomogeneousMatrix &cMo, const vpColVector &desired_normal, const vpColVector ¢roid_point)
Implementation of column vector and the associated operations.
static bool inMask(const vpImage< bool > *mask, unsigned int i, unsigned int j)
static double dotProd(const vpColVector &a, const vpColVector &b)
double get_x() const
Get the point x coordinate in the image plane.
void setRight(double pos)
vpMbHiddenFaces< vpMbtPolygon > * hiddenface
Pointer to the list of faces.
double get_y() const
Get the point y coordinate in the image plane.
void displayFeature(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, double scale=0.05, unsigned int thickness=1)
void addPolygon(const int &index)
void setNearClippingDistance(const double &dist)
vpPoint m_faceDesiredCentroid
Desired centroid (computed from the sensor)
Defines a rectangle in the plane.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Compute the geometric centroid.
virtual ~vpMbtFaceDepthNormal()
double get_Z() const
Get the point Z coordinate in the camera frame.
vpPlane m_planeObject
Plane equation described in the object frame.
void changeFrame(const vpHomogeneousMatrix &cMo, vpColVector &_cP)
double get_Y() const
Get the point Y coordinate in the camera frame.
bool computeDesiredFeatures(const vpHomogeneousMatrix &cMo, unsigned int width, unsigned int height, const pcl::PointCloud< pcl::PointXYZ >::ConstPtr &point_cloud, vpColVector &desired_features, unsigned int stepX, unsigned int stepY, const vpImage< bool > *mask=NULL)
void estimateFeatures(const std::vector< double > &point_cloud_face, const vpHomogeneousMatrix &cMo, vpColVector &x_estimated, std::vector< double > &weights)
unsigned int getWidth() const
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
void setBottom(double pos)
void display(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, const vpColor &col, unsigned int thickness=1, bool displayFullModel=false)
bool useScanLine
Use scanline rendering.
void set_X(double X)
Set the point X coordinate in the camera frame.
void buildFrom(vpPoint &_p1, vpPoint &_p2)
void setIndex(unsigned int i)
static const vpColor blue
double m_pclPlaneEstimationRansacThreshold
PCL plane estimation RANSAC threshold.
void computeFov(const unsigned int &w, const unsigned int &h)