194 const pcl::PointCloud<pcl::PointXYZ>::ConstPtr &point_cloud,
195 vpColVector &desired_features,
unsigned int stepX,
unsigned int stepY
196#
if DEBUG_DISPLAY_DEPTH_NORMAL
199 std::vector<std::vector<vpImagePoint> > &roiPts_vec
206 if (width == 0 || height == 0)
209 std::vector<vpImagePoint> roiPts;
213#
if DEBUG_DISPLAY_DEPTH_NORMAL
219 if (roiPts.size() <= 2) {
221 std::cerr <<
"Error: roiPts.size() <= 2 in computeDesiredFeatures" << std::endl;
229 unsigned int top =
static_cast<unsigned int>(std::max<double>(0.0, bb.getTop()));
230 unsigned int bottom =
static_cast<unsigned int>(std::min<double>(
static_cast<double>(height), std::max<double>(0.0, bb.getBottom())));
231 unsigned int left =
static_cast<unsigned int>(std::max<double>(0.0, bb.getLeft()));
232 unsigned int right =
static_cast<unsigned int>(std::min<double>(
static_cast<double>(width), std::max<double>(0.0, bb.getRight())));
235 bb.setBottom(bottom);
240 pcl::PointCloud<pcl::PointXYZ>::Ptr point_cloud_face(
new pcl::PointCloud<pcl::PointXYZ>);
241 std::vector<double> point_cloud_face_vec, point_cloud_face_custom;
244 point_cloud_face_custom.reserve(
static_cast<size_t>(3 * bb.getWidth() * bb.getHeight()));
245 point_cloud_face_vec.reserve(
static_cast<size_t>(3 * bb.getWidth() * bb.getHeight()));
248 point_cloud_face_vec.reserve(
static_cast<size_t>(3 * bb.getWidth() * bb.getHeight()));
251 point_cloud_face->reserve(
static_cast<size_t>(bb.getWidth() * bb.getHeight()));
259 double prev_x, prev_y, prev_z;
262 double x = 0.0, y = 0.0;
263 for (
unsigned int i = top; i < bottom; i += stepY) {
264 for (
unsigned int j = left; j < right; j += stepX) {
265 if (
vpMeTracker::inRoiMask(mask, i, j) && pcl::isFinite((*point_cloud)(j, i)) && (*point_cloud)(j, i).z > 0 &&
266 (
m_useScanLine ? (i < m_hiddenFace->getMbScanLineRenderer().getPrimitiveIDs().getHeight() &&
267 j < m_hiddenFace->getMbScanLineRenderer().getPrimitiveIDs().getWidth() &&
272 point_cloud_face->push_back((*point_cloud)(j, i));
276 point_cloud_face_vec.push_back((*point_cloud)(j, i).x);
277 point_cloud_face_vec.push_back((*point_cloud)(j, i).y);
278 point_cloud_face_vec.push_back((*point_cloud)(j, i).z);
290 prev_z = (*point_cloud)(j, i).z;
294 point_cloud_face_custom.push_back(prev_x);
295 point_cloud_face_custom.push_back(x);
297 point_cloud_face_custom.push_back(prev_y);
298 point_cloud_face_custom.push_back(y);
300 point_cloud_face_custom.push_back(prev_z);
301 point_cloud_face_custom.push_back((*point_cloud)(j, i).z);
306 point_cloud_face_custom.push_back(x);
307 point_cloud_face_custom.push_back(y);
308 point_cloud_face_custom.push_back((*point_cloud)(j, i).z);
313#if DEBUG_DISPLAY_DEPTH_NORMAL
314 debugImage[i][j] = 255;
321 if (checkSSE2 && push) {
322 point_cloud_face_custom.push_back(prev_x);
323 point_cloud_face_custom.push_back(prev_y);
324 point_cloud_face_custom.push_back(prev_z);
328 if (point_cloud_face->empty() && point_cloud_face_custom.empty() && point_cloud_face_vec.empty()) {
345 desired_normal, centroid_point);
360 unsigned int height,
const std::vector<vpColVector> &point_cloud,
361 vpColVector &desired_features,
unsigned int stepX,
unsigned int stepY
362#
if DEBUG_DISPLAY_DEPTH_NORMAL
365 std::vector<std::vector<vpImagePoint> > &roiPts_vec
372 if (width == 0 || height == 0)
375 std::vector<vpImagePoint> roiPts;
379#
if DEBUG_DISPLAY_DEPTH_NORMAL
385 if (roiPts.size() <= 2) {
387 std::cerr <<
"Error: roiPts.size() <= 2 in computeDesiredFeatures" << std::endl;
395 unsigned int top =
static_cast<unsigned int>(std::max<double>(0.0, bb.getTop()));
396 unsigned int bottom =
static_cast<unsigned int>(std::min<double>(
static_cast<double>(height), std::max<double>(0.0, bb.getBottom())));
397 unsigned int left =
static_cast<unsigned int>(std::max<double>(0.0, bb.getLeft()));
398 unsigned int right =
static_cast<unsigned int>(std::min<double>(
static_cast<double>(width), std::max<double>(0.0, bb.getRight())));
401 bb.setBottom(bottom);
406 std::vector<double> point_cloud_face, point_cloud_face_custom;
408 point_cloud_face.reserve(
static_cast<size_t>(3 * bb.getWidth() * bb.getHeight()));
410 point_cloud_face_custom.reserve(
static_cast<size_t>(3 * bb.getWidth() * bb.getHeight()));
418 double prev_x, prev_y, prev_z;
421 double x = 0.0, y = 0.0;
422 for (
unsigned int i = top; i < bottom; i += stepY) {
423 for (
unsigned int j = left; j < right; j += stepX) {
425 (
m_useScanLine ? (i < m_hiddenFace->getMbScanLineRenderer().getPrimitiveIDs().getHeight() &&
426 j < m_hiddenFace->getMbScanLineRenderer().getPrimitiveIDs().getWidth() &&
430 point_cloud_face.push_back(point_cloud[i * width + j][0]);
431 point_cloud_face.push_back(point_cloud[i * width + j][1]);
432 point_cloud_face.push_back(point_cloud[i * width + j][2]);
444 prev_z = point_cloud[i * width + j][2];
448 point_cloud_face_custom.push_back(prev_x);
449 point_cloud_face_custom.push_back(x);
451 point_cloud_face_custom.push_back(prev_y);
452 point_cloud_face_custom.push_back(y);
454 point_cloud_face_custom.push_back(prev_z);
455 point_cloud_face_custom.push_back(point_cloud[i * width + j][2]);
460 point_cloud_face_custom.push_back(x);
461 point_cloud_face_custom.push_back(y);
462 point_cloud_face_custom.push_back(point_cloud[i * width + j][2]);
466#if DEBUG_DISPLAY_DEPTH_NORMAL
467 debugImage[i][j] = 255;
474 if (checkSSE2 && push) {
475 point_cloud_face_custom.push_back(prev_x);
476 point_cloud_face_custom.push_back(prev_y);
477 point_cloud_face_custom.push_back(prev_z);
481 if (point_cloud_face.empty() && point_cloud_face_custom.empty()) {
488#if defined(VISP_HAVE_PCL) && defined(VISP_HAVE_PCL_SEGMENTATION) && defined(VISP_HAVE_PCL_FILTERS) && defined(VISP_HAVE_PCL_COMMON)
490 pcl::PointCloud<pcl::PointXYZ>::Ptr point_cloud_face_pcl(
new pcl::PointCloud<pcl::PointXYZ>);
491 point_cloud_face_pcl->reserve(point_cloud_face.size() / 3);
493 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
494 point_cloud_face_pcl->push_back(
495 pcl::PointXYZ(point_cloud_face[3 * i], point_cloud_face[3 * i + 1], point_cloud_face[3 * i + 2]));
507 desired_normal, centroid_point);
521 unsigned int height,
const vpMatrix &point_cloud,
522 vpColVector &desired_features,
unsigned int stepX,
unsigned int stepY
523#
if DEBUG_DISPLAY_DEPTH_NORMAL
526 std::vector<std::vector<vpImagePoint> > &roiPts_vec
533 if (width == 0 || height == 0)
536 std::vector<vpImagePoint> roiPts;
540#
if DEBUG_DISPLAY_DEPTH_NORMAL
546 if (roiPts.size() <= 2) {
548 std::cerr <<
"Error: roiPts.size() <= 2 in computeDesiredFeatures" << std::endl;
556 unsigned int top =
static_cast<unsigned int>(std::max<double>(0.0, bb.getTop()));
557 unsigned int bottom =
static_cast<unsigned int>(std::min<double>(
static_cast<double>(height), std::max<double>(0.0, bb.getBottom())));
558 unsigned int left =
static_cast<unsigned int>(std::max<double>(0.0, bb.getLeft()));
559 unsigned int right =
static_cast<unsigned int>(std::min<double>(
static_cast<double>(width), std::max<double>(0.0, bb.getRight())));
562 bb.setBottom(bottom);
567 std::vector<double> point_cloud_face, point_cloud_face_custom;
569 point_cloud_face.reserve(
static_cast<size_t>(3 * bb.getWidth() * bb.getHeight()));
571 point_cloud_face_custom.reserve(
static_cast<size_t>(3 * bb.getWidth() * bb.getHeight()));
579 double prev_x, prev_y, prev_z;
582 double x = 0.0, y = 0.0;
583 for (
unsigned int i = top; i < bottom; i += stepY) {
584 for (
unsigned int j = left; j < right; j += stepX) {
586 (
m_useScanLine ? (i < m_hiddenFace->getMbScanLineRenderer().getPrimitiveIDs().getHeight() &&
587 j < m_hiddenFace->getMbScanLineRenderer().getPrimitiveIDs().getWidth() &&
591 point_cloud_face.push_back(point_cloud[i * width + j][0]);
592 point_cloud_face.push_back(point_cloud[i * width + j][1]);
593 point_cloud_face.push_back(point_cloud[i * width + j][2]);
605 prev_z = point_cloud[i * width + j][2];
609 point_cloud_face_custom.push_back(prev_x);
610 point_cloud_face_custom.push_back(x);
612 point_cloud_face_custom.push_back(prev_y);
613 point_cloud_face_custom.push_back(y);
615 point_cloud_face_custom.push_back(prev_z);
616 point_cloud_face_custom.push_back(point_cloud[i * width + j][2]);
621 point_cloud_face_custom.push_back(x);
622 point_cloud_face_custom.push_back(y);
623 point_cloud_face_custom.push_back(point_cloud[i * width + j][2]);
627#if DEBUG_DISPLAY_DEPTH_NORMAL
628 debugImage[i][j] = 255;
635 if (checkSSE2 && push) {
636 point_cloud_face_custom.push_back(prev_x);
637 point_cloud_face_custom.push_back(prev_y);
638 point_cloud_face_custom.push_back(prev_z);
642 if (point_cloud_face.empty() && point_cloud_face_custom.empty()) {
649#if defined(VISP_HAVE_PCL) && defined(VISP_HAVE_PCL_SEGMENTATION) && defined(VISP_HAVE_PCL_FILTERS) && defined(VISP_HAVE_PCL_COMMON)
651 pcl::PointCloud<pcl::PointXYZ>::Ptr point_cloud_face_pcl(
new pcl::PointCloud<pcl::PointXYZ>);
652 point_cloud_face_pcl->reserve(point_cloud_face.size() / 3);
654 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
655 point_cloud_face_pcl->push_back(
656 pcl::PointXYZ(point_cloud_face[3 * i], point_cloud_face[3 * i + 1], point_cloud_face[3 * i + 2]));
668 desired_normal, centroid_point);
1297 vpMbtTukeyEstimator<double> tukey_robust;
1298 std::vector<double> residues(point_cloud_face.size() / 3);
1300 w.resize(point_cloud_face.size() / 3, 1.0);
1302 unsigned int max_iter = 30, iter = 0;
1303 double error = 0.0, prev_error = -1.0;
1304 double A = 0.0, B = 0.0, C = 0.0;
1306 Mat33<double> ATA_3x3;
1315 while (std::fabs(error - prev_error) > 1e-6 && (iter < max_iter)) {
1332 if (point_cloud_face.size() / 3 >= 2) {
1333 const double *ptr_point_cloud = &point_cloud_face[0];
1334 const __m128d vA = _mm_set1_pd(A);
1335 const __m128d vB = _mm_set1_pd(B);
1336 const __m128d vC = _mm_set1_pd(C);
1337 const __m128d vones = _mm_set1_pd(1.0);
1339 double *ptr_residues = &residues[0];
1341 for (; cpt <= point_cloud_face.size() - 6; cpt += 6, ptr_point_cloud += 6, ptr_residues += 2) {
1342 const __m128d vxi = _mm_loadu_pd(ptr_point_cloud);
1343 const __m128d vyi = _mm_loadu_pd(ptr_point_cloud + 2);
1344 const __m128d vZi = _mm_loadu_pd(ptr_point_cloud + 4);
1345 const __m128d vinvZi = _mm_div_pd(vones, vZi);
1348 _mm_add_pd(_mm_add_pd(_mm_mul_pd(vA, vxi), _mm_mul_pd(vB, vyi)), _mm_sub_pd(vC, vinvZi));
1349 _mm_storeu_pd(ptr_residues, tmp);
1353 for (; cpt < point_cloud_face.size(); cpt += 3) {
1354 double xi = point_cloud_face[cpt];
1355 double yi = point_cloud_face[cpt + 1];
1356 double Zi = point_cloud_face[cpt + 2];
1358 residues[cpt / 3] = (A * xi + B * yi + C - 1 / Zi);
1362 tukey_robust.MEstimator(residues, w, 1e-2);
1364 __m128d vsum_wi2_xi2 = _mm_setzero_pd();
1365 __m128d vsum_wi2_yi2 = _mm_setzero_pd();
1366 __m128d vsum_wi2 = _mm_setzero_pd();
1367 __m128d vsum_wi2_xi_yi = _mm_setzero_pd();
1368 __m128d vsum_wi2_xi = _mm_setzero_pd();
1369 __m128d vsum_wi2_yi = _mm_setzero_pd();
1371 __m128d vsum_wi2_xi_Zi = _mm_setzero_pd();
1372 __m128d vsum_wi2_yi_Zi = _mm_setzero_pd();
1373 __m128d vsum_wi2_Zi = _mm_setzero_pd();
1377 if (point_cloud_face.size() / 3 >= 2) {
1378 const double *ptr_point_cloud = &point_cloud_face[0];
1379 double *ptr_w = &w[0];
1381 const __m128d vones = _mm_set1_pd(1.0);
1383 for (; cpt <= point_cloud_face.size() - 6; cpt += 6, ptr_point_cloud += 6, ptr_w += 2) {
1384 const __m128d vwi2 = _mm_mul_pd(_mm_loadu_pd(ptr_w), _mm_loadu_pd(ptr_w));
1386 const __m128d vxi = _mm_loadu_pd(ptr_point_cloud);
1387 const __m128d vyi = _mm_loadu_pd(ptr_point_cloud + 2);
1388 const __m128d vZi = _mm_loadu_pd(ptr_point_cloud + 4);
1389 const __m128d vinvZi = _mm_div_pd(vones, vZi);
1391 vsum_wi2_xi2 = _mm_add_pd(vsum_wi2_xi2, _mm_mul_pd(vwi2, _mm_mul_pd(vxi, vxi)));
1392 vsum_wi2_yi2 = _mm_add_pd(vsum_wi2_yi2, _mm_mul_pd(vwi2, _mm_mul_pd(vyi, vyi)));
1393 vsum_wi2 = _mm_add_pd(vsum_wi2, vwi2);
1394 vsum_wi2_xi_yi = _mm_add_pd(vsum_wi2_xi_yi, _mm_mul_pd(vwi2, _mm_mul_pd(vxi, vyi)));
1395 vsum_wi2_xi = _mm_add_pd(vsum_wi2_xi, _mm_mul_pd(vwi2, vxi));
1396 vsum_wi2_yi = _mm_add_pd(vsum_wi2_yi, _mm_mul_pd(vwi2, vyi));
1398 const __m128d vwi2_invZi = _mm_mul_pd(vwi2, vinvZi);
1399 vsum_wi2_xi_Zi = _mm_add_pd(vsum_wi2_xi_Zi, _mm_mul_pd(vxi, vwi2_invZi));
1400 vsum_wi2_yi_Zi = _mm_add_pd(vsum_wi2_yi_Zi, _mm_mul_pd(vyi, vwi2_invZi));
1401 vsum_wi2_Zi = _mm_add_pd(vsum_wi2_Zi, vwi2_invZi);
1406 _mm_storeu_pd(vtmp, vsum_wi2_xi2);
1407 double sum_wi2_xi2 = vtmp[0] + vtmp[1];
1409 _mm_storeu_pd(vtmp, vsum_wi2_yi2);
1410 double sum_wi2_yi2 = vtmp[0] + vtmp[1];
1412 _mm_storeu_pd(vtmp, vsum_wi2);
1413 double sum_wi2 = vtmp[0] + vtmp[1];
1415 _mm_storeu_pd(vtmp, vsum_wi2_xi_yi);
1416 double sum_wi2_xi_yi = vtmp[0] + vtmp[1];
1418 _mm_storeu_pd(vtmp, vsum_wi2_xi);
1419 double sum_wi2_xi = vtmp[0] + vtmp[1];
1421 _mm_storeu_pd(vtmp, vsum_wi2_yi);
1422 double sum_wi2_yi = vtmp[0] + vtmp[1];
1424 _mm_storeu_pd(vtmp, vsum_wi2_xi_Zi);
1425 double sum_wi2_xi_Zi = vtmp[0] + vtmp[1];
1427 _mm_storeu_pd(vtmp, vsum_wi2_yi_Zi);
1428 double sum_wi2_yi_Zi = vtmp[0] + vtmp[1];
1430 _mm_storeu_pd(vtmp, vsum_wi2_Zi);
1431 double sum_wi2_Zi = vtmp[0] + vtmp[1];
1433 for (; cpt < point_cloud_face.size(); cpt += 3) {
1434 double wi2 = w[cpt / 3] * w[cpt / 3];
1436 double xi = point_cloud_face[cpt];
1437 double yi = point_cloud_face[cpt + 1];
1438 double Zi = point_cloud_face[cpt + 2];
1439 double invZi = 1.0 / Zi;
1441 sum_wi2_xi2 += wi2 * xi * xi;
1442 sum_wi2_yi2 += wi2 * yi * yi;
1444 sum_wi2_xi_yi += wi2 * xi * yi;
1445 sum_wi2_xi += wi2 * xi;
1446 sum_wi2_yi += wi2 * yi;
1448 sum_wi2_xi_Zi += wi2 * xi * invZi;
1449 sum_wi2_yi_Zi += wi2 * yi * invZi;
1450 sum_wi2_Zi += wi2 * invZi;
1453 ATA_3x3[0] = sum_wi2_xi2;
1454 ATA_3x3[1] = sum_wi2_xi_yi;
1455 ATA_3x3[2] = sum_wi2_xi;
1456 ATA_3x3[3] = sum_wi2_xi_yi;
1457 ATA_3x3[4] = sum_wi2_yi2;
1458 ATA_3x3[5] = sum_wi2_yi;
1459 ATA_3x3[6] = sum_wi2_xi;
1460 ATA_3x3[7] = sum_wi2_yi;
1461 ATA_3x3[8] = sum_wi2;
1463 Mat33<double> minv = ATA_3x3.inverse();
1465 A = minv[0] * sum_wi2_xi_Zi + minv[1] * sum_wi2_yi_Zi + minv[2] * sum_wi2_Zi;
1466 B = minv[3] * sum_wi2_xi_Zi + minv[4] * sum_wi2_yi_Zi + minv[5] * sum_wi2_Zi;
1467 C = minv[6] * sum_wi2_xi_Zi + minv[7] * sum_wi2_yi_Zi + minv[8] * sum_wi2_Zi;
1475 __m128d verror = _mm_set1_pd(0.0);
1476 if (point_cloud_face.size() / 3 >= 2) {
1477 const double *ptr_point_cloud = &point_cloud_face[0];
1478 const __m128d vA = _mm_set1_pd(A);
1479 const __m128d vB = _mm_set1_pd(B);
1480 const __m128d vC = _mm_set1_pd(C);
1481 const __m128d vones = _mm_set1_pd(1.0);
1483 double *ptr_residues = &residues[0];
1485 for (; cpt <= point_cloud_face.size() - 6; cpt += 6, ptr_point_cloud += 6, ptr_residues += 2) {
1486 const __m128d vxi = _mm_loadu_pd(ptr_point_cloud);
1487 const __m128d vyi = _mm_loadu_pd(ptr_point_cloud + 2);
1488 const __m128d vZi = _mm_loadu_pd(ptr_point_cloud + 4);
1489 const __m128d vinvZi = _mm_div_pd(vones, vZi);
1491 const __m128d tmp = _mm_add_pd(_mm_add_pd(_mm_mul_pd(vA, vxi), _mm_mul_pd(vB, vyi)), _mm_sub_pd(vC, vinvZi));
1492 verror = _mm_add_pd(verror, _mm_mul_pd(tmp, tmp));
1494 _mm_storeu_pd(ptr_residues, tmp);
1498 _mm_storeu_pd(vtmp, verror);
1499 error = vtmp[0] + vtmp[1];
1501 for (
size_t idx = cpt; idx < point_cloud_face.size(); idx += 3) {
1502 double xi = point_cloud_face[idx];
1503 double yi = point_cloud_face[idx + 1];
1504 double Zi = point_cloud_face[idx + 2];
1506 error +=
vpMath::sqr(A * xi + B * yi + C - 1 / Zi);
1507 residues[idx / 3] = (A * xi + B * yi + C - 1 / Zi);
1510 error /= point_cloud_face.size() / 3;
1517 while (std::fabs(error - prev_error) > 1e-6 && (iter < max_iter)) {
1533 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1534 double xi = point_cloud_face[3 * i];
1535 double yi = point_cloud_face[3 * i + 1];
1536 double Zi = point_cloud_face[3 * i + 2];
1538 residues[i] = (A * xi + B * yi + C - 1 / Zi);
1542 tukey_robust.MEstimator(residues, w, 1e-2);
1545 double sum_wi2_xi2 = 0.0, sum_wi2_yi2 = 0.0, sum_wi2 = 0.0;
1546 double sum_wi2_xi_yi = 0.0, sum_wi2_xi = 0.0, sum_wi2_yi = 0.0;
1548 double sum_wi2_xi_Zi = 0.0, sum_wi2_yi_Zi = 0.0, sum_wi2_Zi = 0.0;
1550 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1551 double wi2 = w[i] * w[i];
1553 double xi = point_cloud_face[3 * i];
1554 double yi = point_cloud_face[3 * i + 1];
1555 double Zi = point_cloud_face[3 * i + 2];
1556 double invZi = 1 / Zi;
1558 sum_wi2_xi2 += wi2 * xi * xi;
1559 sum_wi2_yi2 += wi2 * yi * yi;
1561 sum_wi2_xi_yi += wi2 * xi * yi;
1562 sum_wi2_xi += wi2 * xi;
1563 sum_wi2_yi += wi2 * yi;
1565 sum_wi2_xi_Zi += wi2 * xi * invZi;
1566 sum_wi2_yi_Zi += wi2 * yi * invZi;
1567 sum_wi2_Zi += wi2 * invZi;
1570 ATA_3x3[0] = sum_wi2_xi2;
1571 ATA_3x3[1] = sum_wi2_xi_yi;
1572 ATA_3x3[2] = sum_wi2_xi;
1573 ATA_3x3[3] = sum_wi2_xi_yi;
1574 ATA_3x3[4] = sum_wi2_yi2;
1575 ATA_3x3[5] = sum_wi2_yi;
1576 ATA_3x3[6] = sum_wi2_xi;
1577 ATA_3x3[7] = sum_wi2_yi;
1578 ATA_3x3[8] = sum_wi2;
1580 Mat33<double> minv = ATA_3x3.inverse();
1582 A = minv[0] * sum_wi2_xi_Zi + minv[1] * sum_wi2_yi_Zi + minv[2] * sum_wi2_Zi;
1583 B = minv[3] * sum_wi2_xi_Zi + minv[4] * sum_wi2_yi_Zi + minv[5] * sum_wi2_Zi;
1584 C = minv[6] * sum_wi2_xi_Zi + minv[7] * sum_wi2_yi_Zi + minv[8] * sum_wi2_Zi;
1590 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1591 double xi = point_cloud_face[3 * i];
1592 double yi = point_cloud_face[3 * i + 1];
1593 double Zi = point_cloud_face[3 * i + 2];
1595 error +=
vpMath::sqr(A * xi + B * yi + C - 1 / Zi);
1596 residues[i] = (A * xi + B * yi + C - 1 / Zi);
1599 error /= point_cloud_face.size() / 3;
1605 x_estimated.
resize(3,
false);
1615 unsigned int max_iter = 10;
1616 double prev_error = 1e3;
1617 double error = 1e3 - 1;
1619 std::vector<double> weights(point_cloud_face.size() / 3, 1.0);
1620 std::vector<double> residues(point_cloud_face.size() / 3);
1621 vpMatrix M(
static_cast<unsigned int>(point_cloud_face.size() / 3), 3);
1622 vpMbtTukeyEstimator<double> tukey;
1625 for (
unsigned int iter = 0; iter < max_iter && std::fabs(error - prev_error) > 1e-6; iter++) {
1627 tukey.MEstimator(residues, weights, 1e-4);
1640 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1641 residues[i] = std::fabs(A * point_cloud_face[3 * i] + B * point_cloud_face[3 * i + 1] +
1642 C * point_cloud_face[3 * i + 2] + D) /
1643 sqrt(A * A + B * B + C * C);
1646 tukey.MEstimator(residues, weights, 1e-4);
1647 plane_equation_estimated.
resize(4,
false);
1651 double centroid_x = 0.0, centroid_y = 0.0, centroid_z = 0.0;
1652 double total_w = 0.0;
1654 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1655 centroid_x += weights[i] * point_cloud_face[3 * i];
1656 centroid_y += weights[i] * point_cloud_face[3 * i + 1];
1657 centroid_z += weights[i] * point_cloud_face[3 * i + 2];
1658 total_w += weights[i];
1661 centroid_x /= total_w;
1662 centroid_y /= total_w;
1663 centroid_z /= total_w;
1666 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1667 M[
static_cast<unsigned int>(i)][0] = weights[i] * (point_cloud_face[3 * i] - centroid_x);
1668 M[
static_cast<unsigned int>(i)][1] = weights[i] * (point_cloud_face[3 * i + 1] - centroid_y);
1669 M[
static_cast<unsigned int>(i)][2] = weights[i] * (point_cloud_face[3 * i + 2] - centroid_z);
1678 double smallestSv = W[0];
1679 unsigned int indexSmallestSv = 0;
1680 for (
unsigned int i = 1; i < W.
size(); i++) {
1681 if (W[i] < smallestSv) {
1683 indexSmallestSv = i;
1687 normal = V.
getCol(indexSmallestSv);
1690 double A = normal[0], B = normal[1], C = normal[2];
1691 double D = -(A * centroid_x + B * centroid_y + C * centroid_z);
1694 plane_equation_estimated[0] = A;
1695 plane_equation_estimated[1] = B;
1696 plane_equation_estimated[2] = C;
1697 plane_equation_estimated[3] = D;
1702 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1703 residues[i] = std::fabs(A * point_cloud_face[3 * i] + B * point_cloud_face[3 * i + 1] +
1704 C * point_cloud_face[3 * i + 2] + D) /
1705 sqrt(A * A + B * B + C * C);
1706 error += weights[i] * residues[i];
1712 tukey.MEstimator(residues, weights, 1e-4);
1715 centroid.
resize(3,
false);
1716 double total_w = 0.0;
1718 for (
size_t i = 0; i < point_cloud_face.size() / 3; i++) {
1719 centroid[0] += weights[i] * point_cloud_face[3 * i];
1720 centroid[1] += weights[i] * point_cloud_face[3 * i + 1];
1721 centroid[2] += weights[i] * point_cloud_face[3 * i + 2];
1722 total_w += weights[i];
1725 centroid[0] /= total_w;
1726 centroid[1] /= total_w;
1727 centroid[2] /= total_w;
1730 double A = normal[0], B = normal[1], C = normal[2];
1731 double D = -(A * centroid[0] + B * centroid[1] + C * centroid[2]);
1734 plane_equation_estimated[0] = A;
1735 plane_equation_estimated[1] = B;
1736 plane_equation_estimated[2] = C;
1737 plane_equation_estimated[3] = D;