27 #include <Eigen/Dense> 45 CFaceDetection::CFaceDetection()
47 m_measure.numPossibleFacesDetected = 0;
48 m_measure.numRealFacesDetected = 0;
50 m_measure.faceNum = 0;
58 CFaceDetection::~CFaceDetection()
64 m_enter_checkIfFacePlaneCov.set_value();
65 m_enter_checkIfFaceRegions.set_value();
66 m_enter_checkIfDiagonalSurface.set_value();
68 m_thread_checkIfFaceRegions.join();
69 m_thread_checkIfFacePlaneCov.join();
70 m_thread_checkIfDiagonalSurface.join();
78 m_options.confidenceThreshold =
79 cfg.
read_int(
"FaceDetection",
"confidenceThreshold", 240);
80 m_options.multithread = cfg.
read_bool(
"FaceDetection",
"multithread",
true);
81 m_options.useCovFilter =
82 cfg.
read_bool(
"FaceDetection",
"useCovFilter",
true);
83 m_options.useRegionsFilter =
84 cfg.
read_bool(
"FaceDetection",
"useRegionsFilter",
true);
85 m_options.useSizeDistanceRelationFilter =
86 cfg.
read_bool(
"FaceDetection",
"useSizeDistanceRelationFilter",
true);
87 m_options.useDiagonalDistanceFilter =
88 cfg.
read_bool(
"FaceDetection",
"useDiagonalDistanceFilter",
true);
90 m_testsOptions.planeThreshold =
91 cfg.
read_double(
"FaceDetection",
"planeThreshold", 50);
92 m_testsOptions.planeTest_eigenVal_top =
93 cfg.
read_double(
"FaceDetection",
"planeTest_eigenVal_top", 0.011);
94 m_testsOptions.planeTest_eigenVal_bottom =
95 cfg.
read_double(
"FaceDetection",
"planeTest_eigenVal_bottom", 0.0002);
96 m_testsOptions.regionsTest_sumDistThreshold_top = cfg.
read_double(
97 "FaceDetection",
"regionsTest_sumDistThreshold_top", 0.5);
98 m_testsOptions.regionsTest_sumDistThreshold_bottom = cfg.
read_double(
99 "FaceDetection",
"regionsTest_sumDistThreshold_bottom", 0.04);
101 m_measure.takeTime = cfg.
read_bool(
"FaceDetection",
"takeTime",
false);
102 m_measure.takeMeasures =
103 cfg.
read_bool(
"FaceDetection",
"takeMeasures",
false);
104 m_measure.saveMeasurementsToFile =
105 cfg.
read_bool(
"FaceDetection",
"saveMeasurementsToFile",
false);
108 if (m_options.multithread)
110 if (m_options.useRegionsFilter)
111 m_thread_checkIfFaceRegions =
112 std::thread(dummy_checkIfFaceRegions,
this);
113 if (m_options.useCovFilter)
114 m_thread_checkIfFacePlaneCov =
115 std::thread(dummy_checkIfFacePlaneCov,
this);
116 if (m_options.useSizeDistanceRelationFilter ||
117 m_options.useDiagonalDistanceFilter)
118 m_thread_checkIfDiagonalSurface =
119 std::thread(dummy_checkIfDiagonalSurface,
this);
121 m_checkIfFacePlaneCov_res =
false;
122 m_checkIfFaceRegions_res =
true;
123 m_checkIfDiagonalSurface_res =
true;
126 cascadeClassifier.init(cfg);
132 void CFaceDetection::detectObjects_Impl(
142 if (m_measure.takeTime) m_timeLog.enter(
"Detection time");
145 cascadeClassifier.detectObjects(obs, localDetected);
149 if (m_measure.takeTime) m_timeLog.leave(
"Detection time");
152 m_measure.numPossibleFacesDetected += localDetected.size();
160 if (m_measure.takeTime) m_timeLog.enter(
"Check if real face time");
169 vector<size_t> deleteDetected;
173 for (
unsigned int i = 0; i < localDetected.size(); i++)
179 unsigned int r1 = rec->m_y;
180 unsigned int r2 = rec->m_y + rec->m_height;
181 unsigned int c1 = rec->m_x;
182 unsigned int c2 = rec->m_x + rec->m_width;
184 o.getZoneAsObs(m_lastFaceDetected, r1, r2, c1, c2);
186 if (m_options.multithread)
190 if (m_measure.takeTime)
191 m_timeLog.enter(
"Multithread filters application");
195 if (m_options.useCovFilter)
196 m_enter_checkIfFacePlaneCov.set_value();
197 if (m_options.useRegionsFilter)
198 m_enter_checkIfFaceRegions.set_value();
199 if (m_options.useSizeDistanceRelationFilter ||
200 m_options.useDiagonalDistanceFilter)
201 m_enter_checkIfDiagonalSurface.set_value();
204 if (m_options.useCovFilter)
205 m_leave_checkIfFacePlaneCov.get_future().wait();
206 if (m_options.useRegionsFilter)
207 m_leave_checkIfFaceRegions.get_future().wait();
208 if (m_options.useSizeDistanceRelationFilter ||
209 m_options.useDiagonalDistanceFilter)
210 m_leave_checkIfDiagonalSurface.get_future().wait();
213 if (!m_checkIfFacePlaneCov_res ||
214 !m_checkIfFaceRegions_res ||
215 !m_checkIfDiagonalSurface_res)
216 deleteDetected.push_back(i);
220 if (m_measure.takeTime)
221 m_timeLog.leave(
"Multithread filters application");
230 if (m_measure.takeTime)
231 m_timeLog.enter(
"Secuential filters application");
245 if (m_options.useCovFilter &&
246 !checkIfFacePlaneCov(&m_lastFaceDetected))
248 deleteDetected.push_back(i);
252 m_options.useRegionsFilter &&
253 !checkIfFaceRegions(&m_lastFaceDetected))
255 deleteDetected.push_back(i);
259 (m_options.useSizeDistanceRelationFilter ||
260 m_options.useDiagonalDistanceFilter) &&
261 !checkIfDiagonalSurface(&m_lastFaceDetected))
263 deleteDetected.push_back(i);
273 m_measure.deletedRegions.push_back(m_measure.faceNum);
280 if (m_measure.takeTime)
281 m_timeLog.leave(
"Secuential filters application");
287 for (
unsigned int i = deleteDetected.size(); i > 0; i--)
289 localDetected.begin() + deleteDetected[i - 1]);
293 for (
const auto& i : localDetected)
295 auto object3d = std::make_shared<CDetectable3D>(
297 detected.push_back(object3d);
302 if (m_measure.takeTime) m_timeLog.leave(
"Check if real face time");
307 detected = localDetected;
313 m_measure.numRealFacesDetected += detected.size();
324 vector<TPoint3D> points;
330 for (
size_t i = 0; i < N; i++)
340 if (m_measure.takeMeasures)
341 m_measure.errorEstimations.push_back(
356 void CFaceDetection::thread_checkIfFacePlaneCov()
360 m_enter_checkIfFacePlaneCov.get_future().wait();
362 if (m_end_threads)
break;
365 m_checkIfFacePlaneCov_res = checkIfFacePlaneCov(&m_lastFaceDetected);
367 m_leave_checkIfFacePlaneCov.set_value();
380 if (m_measure.takeTime)
381 m_timeLog.enter(
"Check if face plane: covariance");
392 vector<CVectorFixedDouble<3>> pointsVector;
395 experimental_segmentFace(*face, region);
397 for (
unsigned int j = 0; j < faceHeight; j++)
399 for (
unsigned int k = 0; k < faceWidth; k++)
408 m_options.confidenceThreshold) &&
411 int position = faceWidth * j + k;
415 pointsVector.push_back(aux);
421 if (pointsVector.empty())
return false;
428 std::vector<double> eVals;
430 cov = covVector<vector<CVectorFixedDouble<3>>,
CMatrixDouble>(pointsVector);
436 if (m_measure.takeMeasures) m_measure.lessEigenVals.push_back(eVals[0]);
438 if (m_measure.takeTime)
439 m_timeLog.leave(
"Check if face plane: covariance");
448 cout << eVals[0] <<
" " << eVals[1] <<
" " << eVals[2] <<
" > ";
449 cout << eVals[0] / eVals[2] << endl;
454 if (m_measure.faceNum >= 314)
455 experimental_viewFacePointsAndEigenVects(pointsVector, eVects, eVals);
460 if (eVals[0] / eVals[2] > 0.06)
482 void CFaceDetection::thread_checkIfFaceRegions()
486 m_enter_checkIfFaceRegions.get_future().wait();
488 if (m_end_threads)
break;
491 m_checkIfFaceRegions_res = checkIfFaceRegions(&m_lastFaceDetected);
493 m_leave_checkIfFaceRegions.set_value();
507 if (m_measure.takeTime) m_timeLog.enter(
"Check if face plane: regions");
515 unsigned int sectionVSize = faceHeight / 3.0;
529 vector<TPoint3D> points;
535 int numPoints[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
537 vector<TPoint3D> regions2[9];
545 experimental_segmentFace(*face, region);
552 size_t start = faceWidth,
end = 0;
554 for (
size_t r = 0; r < region.
rows(); r++)
555 for (
size_t c = 1; c < region.
cols(); c++)
557 if ((!(region(r, c - 1))) && (region(r, c)))
559 if (c < start) start = c;
561 else if ((region(r, c - 1)) && (!(region(r, c))))
564 if ((c >
end) && (region(r, c)))
end = c;
567 if (
end == 0)
end = faceWidth - 1;
568 if (
end < 3 * (faceWidth / 4))
569 end = 3 * (faceWidth / 4);
570 if (start == faceWidth) start = 0;
571 if (start > faceWidth / 4) start = faceWidth / 4;
576 unsigned int utilWidth = faceWidth - start - (faceWidth -
end);
577 unsigned int c1 = ceil(utilWidth / 3.0 + start);
578 unsigned int c2 = ceil(2 * (utilWidth / 3.0) + start);
587 experimental_calcHist(
590 size_t countHist = 0;
591 for (
size_t i = 0; i < 60; i++)
593 countHist += hist(0, i);
597 size_t downLimit = faceHeight - 1;
601 upLimit = floor(faceHeight * 0.1);
602 downLimit = floor(faceHeight * 0.9);
613 unsigned int cont = 0;
615 for (
unsigned int r = 0; r < faceHeight; r++)
617 for (
unsigned int c = 0; c < faceWidth; c++, cont++)
619 if ((r >= upLimit) && (r <= downLimit) && (region(r, c)) &&
621 m_options.confidenceThreshold) &&
624 unsigned int row, col;
625 if (r < sectionVSize + upLimit * 0.3)
627 else if (r < sectionVSize * 2 - upLimit * 0.15)
642 meanPos[row][col] = meanPos[row][col] + point;
644 ++numPoints[row][col];
646 if (row == 0 && col == 0)
647 regions2[0].emplace_back(
650 else if (row == 0 && col == 1)
651 regions2[1].emplace_back(
654 else if (row == 0 && col == 2)
655 regions2[2].emplace_back(
658 else if (row == 1 && col == 0)
659 regions2[3].emplace_back(
662 else if (row == 1 && col == 1)
663 regions2[4].emplace_back(
666 else if (row == 1 && col == 2)
667 regions2[5].emplace_back(
670 else if (row == 2 && col == 0)
671 regions2[6].emplace_back(
674 else if (row == 2 && col == 1)
675 regions2[7].emplace_back(
679 regions2[8].emplace_back(
690 vector<double> oldPointsX1;
695 if (regions2[0].
size() > 0)
697 for (
auto& i : regions2[0]) oldPointsX1.push_back(i.x);
699 middle1 = floor((
double)oldPointsX1.size() / 2);
701 oldPointsX1.begin(), oldPointsX1.begin() + middle1,
705 vector<double> oldPointsX2;
707 if (regions2[2].
size() > 0)
709 for (
auto& i : regions2[2]) oldPointsX2.push_back(i.x);
711 middle2 = floor((
double)oldPointsX2.size() / 2);
713 oldPointsX2.begin(), oldPointsX2.begin() + middle2,
717 for (
size_t i = 0; i < 3; i++)
718 for (
size_t j = 0; j < 3; j++)
719 if (!numPoints[i][j])
722 meanPos[i][j] = meanPos[i][j] / numPoints[i][j];
724 if (regions2[0].
size() > 0) meanPos[0][0].
x = oldPointsX1.at(middle1);
726 if (regions2[2].
size() > 0) meanPos[0][2].
x = oldPointsX2.at(middle2);
731 vector<double> dist(5);
732 size_t res = checkRelativePosition(
733 meanPos[1][0], meanPos[1][2], meanPos[1][1], dist[0]);
734 res += res && checkRelativePosition(
735 meanPos[2][0], meanPos[2][2], meanPos[2][1], dist[1]);
736 res += res && checkRelativePosition(
737 meanPos[0][0], meanPos[0][2], meanPos[0][1], dist[2]);
738 res += res && checkRelativePosition(
739 meanPos[0][0], meanPos[2][2], meanPos[1][1], dist[3]);
740 res += res && checkRelativePosition(
741 meanPos[2][0], meanPos[0][2], meanPos[1][1], dist[4]);
744 f.open(
"dist.txt", ofstream::app);
745 f <<
sum(dist) << endl;
751 else if ((res = 1) && (
sum(dist) > 0.04))
754 f.open(
"tam.txt", ofstream::app);
755 f << meanPos[0][1].
distanceTo(meanPos[2][1]) << endl;
769 if (m_measure.takeTime) m_timeLog.leave(
"Check if face plane: regions");
793 size_t CFaceDetection::checkRelativePosition(
805 double yIdeal = y1 + (((x - x1) * (y2 - y1)) / (x2 - x1));
830 void CFaceDetection::thread_checkIfDiagonalSurface()
834 m_enter_checkIfDiagonalSurface.get_future().wait();
836 if (m_end_threads)
break;
839 m_checkIfDiagonalSurface_res =
840 checkIfDiagonalSurface(&m_lastFaceDetected);
842 m_leave_checkIfDiagonalSurface.set_value();
856 if (m_options.useDiagonalDistanceFilter && m_measure.takeTime)
857 m_timeLog.enter(
"Check if face plane: diagonal distances");
859 if (m_options.useSizeDistanceRelationFilter && m_measure.takeTime)
860 m_timeLog.enter(
"Check if face plane: size-distance relation");
868 unsigned int x1 = ceil(faceWidth * 0.25);
869 unsigned int x2 = floor(faceWidth * 0.75);
870 unsigned int y1 = ceil(faceHeight * 0.15);
871 unsigned int y2 = floor(faceHeight * 0.85);
873 vector<TPoint3D> points;
874 unsigned int cont = (y1 == 0 ? 0 : faceHeight * (y1 - 1));
877 valids.
setSize(faceHeight, faceWidth);
882 for (
unsigned int i = y1; i <= y2; i++)
886 for (
unsigned int j = x1; j <= x2; j++, cont++)
889 m_options.confidenceThreshold)
898 cont += faceWidth - x2 - 1;
901 double meanDepth = sumDepth / total;
910 if (m_options.useSizeDistanceRelationFilter)
912 double maxFaceDistance = 0.5 + 1000 / (pow(faceWidth, 1.9));
916 if (m_measure.takeTime)
917 m_timeLog.leave(
"Check if face plane: size-distance relation");
919 if (m_options.useDiagonalDistanceFilter && m_measure.takeTime)
920 m_timeLog.leave(
"Check if face plane: diagonal distances");
929 if (maxFaceDistance < meanDepth)
944 if (!m_options.useDiagonalDistanceFilter)
return true;
952 f.open(
"relaciones2.txt", ofstream::app);
953 f << meanDepth << endl;
962 cont = (y1 == 1 ? 0 : faceHeight * (y1 - 1));
964 for (
unsigned int i = y1; i <= y2; i++)
968 for (
unsigned int j = x1; j <= x2; j++, cont++)
971 m_options.confidenceThreshold))
981 valids(i, j) =
false;
983 cont += faceWidth - x2 - 1;
992 double sumDistances = 0;
998 for (
unsigned int i = y1; i <= y2; i++)
1002 for (
unsigned int j = x1; j <= x2; j++, cont++)
1010 if ((i + 1 <= y2) && (j + 1 <= x2))
1012 if (valids(i + 1, j + 1))
1017 offsetIndex = cont + faceWidth + 1;
1025 bool validOffset =
true;
1030 if ((i + offset <= y2) && (j + offset <= x2))
1032 if (valids(i + offset, j + offset))
1038 offsetIndex = cont + faceWidth + offset;
1048 validOffset =
false;
1056 cont += faceWidth - x2 - 1;
1061 if (m_measure.takeMeasures)
1062 m_measure.sumDistances.push_back(sumDistances);
1065 fo.open(
"distances.txt", ofstream::app);
1067 fo << sumDistances << endl;
1070 fo.open(
"distances2.txt", ofstream::app);
1071 fo << m_measure.faceNum <<
" " << sumDistances << endl;
1077 double yMax = 3 + 6 / (pow(meanDepth, 2));
1078 double yMin = 1 + 3.8 / (pow(meanDepth + 1.2, 2));
1082 if (m_measure.takeTime)
1083 m_timeLog.leave(
"Check if face plane: diagonal distances");
1086 if (((sumDistances <= yMax) && (sumDistances >= yMin)) && (res))
1123 if (m_options.useDiagonalDistanceFilter && m_measure.takeTime)
1124 m_timeLog.enter(
"Check if face plane: diagonal distances");
1126 if (m_options.useSizeDistanceRelationFilter && m_measure.takeTime)
1127 m_timeLog.enter(
"Check if face plane: size-distance relation");
1134 experimental_segmentFace(*face, region);
1140 vector<TPoint3D> points;
1142 for (
unsigned int row = 0; row < faceHeight; row++)
1144 for (
unsigned int col = 0; col < faceWidth; col++, cont++)
1146 if ((region(row, col)) &&
1148 m_options.confidenceThreshold))
1152 points.emplace_back(
1159 double meanDepth = sumDepth / total;
1163 if (m_options.useSizeDistanceRelationFilter)
1165 double maxFaceDistance = 0.5 + 1000 / (pow(faceWidth, 1.9));
1169 if (m_measure.takeTime)
1170 m_timeLog.leave(
"Check if face plane: size-distance relation");
1172 if (m_options.useDiagonalDistanceFilter && m_measure.takeTime)
1173 m_timeLog.leave(
"Check if face plane: diagonal distances");
1182 if (maxFaceDistance < meanDepth)
1197 if (!m_options.useDiagonalDistanceFilter)
return true;
1205 f.open(
"relaciones2.txt", ofstream::app);
1206 f << meanDepth << endl;
1221 double sumDistances = 0;
1223 size_t offsetIndex = 0;
1227 for (
unsigned int i = 0; i < faceHeight; i++)
1229 for (
unsigned int j = 0; j < faceWidth; j++, cont++)
1234 if ((i + 1 < faceHeight) && (j + 1 < faceWidth))
1236 if (region(i + 1, j + 1))
1241 offsetIndex = cont + faceWidth + 1;
1249 bool validOffset =
true;
1254 if ((i + offset < faceHeight) &&
1255 (j + offset < faceWidth))
1257 if (region(i + offset, j + offset))
1263 offsetIndex = cont + faceWidth + offset;
1273 validOffset =
false;
1285 if (m_measure.takeMeasures)
1286 m_measure.sumDistances.push_back(sumDistances);
1289 fo.open(
"distances.txt", ofstream::app);
1291 fo << sumDistances << endl;
1301 double yMax = 3 + 11.8 / (pow(meanDepth, 0.9));
1302 double yMin = 1 + 3.8 / (pow(meanDepth + 7, 6));
1306 if (m_measure.takeTime)
1307 m_timeLog.leave(
"Check if face plane: diagonal distances");
1310 if (((sumDistances <= yMax) && (sumDistances >= yMin)) && (res))
1341 void CFaceDetection::experimental_viewFacePointsScanned(
1344 vector<float> xs, ys, zs;
1352 for (
unsigned int i = 0; i < N; i++)
1359 experimental_viewFacePointsScanned(xs, ys, zs);
1366 void CFaceDetection::experimental_viewFacePointsScanned(
1367 const vector<TPoint3D>& points)
1369 vector<float> xs, ys, zs;
1371 unsigned int N = points.size();
1377 for (
unsigned int i = 0; i < N; i++)
1379 xs[i] = points[i].x;
1380 ys[i] = points[i].y;
1381 zs[i] = points[i].z;
1384 experimental_viewFacePointsScanned(xs, ys, zs);
1391 void CFaceDetection::experimental_viewFacePointsScanned(
1392 const vector<float>& xs,
const vector<float>& ys,
const vector<float>& zs)
1407 gl_points->setPointSize(4.5);
1411 scene->insert(gl_points);
1418 gl_points->loadFromPointsMap(&pntsMap);
1461 void CFaceDetection::experimental_viewFacePointsAndEigenVects(
1463 const CMatrixDouble& eigenVect,
const std::vector<double>& eigenVal)
1465 vector<float> xs, ys, zs;
1467 const size_t size = pointsVector.size();
1473 for (
size_t i = 0; i <
size; i++)
1475 xs[i] = pointsVector[i][0];
1476 ys[i] = pointsVector[i][1];
1477 zs[i] = pointsVector[i][2];
1495 gl_points->setPointSize(4.5);
1499 CSphere::Ptr sphere = std::make_shared<CSphere>(0.005f);
1500 sphere->setLocation(center);
1501 sphere->setColor(
TColorf(0, 1, 0));
1502 scene->insert(sphere);
1504 TPoint3D E1(eigenVect(0, 0), eigenVect(0, 1), eigenVect(0, 2));
1505 TPoint3D E2(eigenVect(1, 0), eigenVect(1, 1), eigenVect(1, 2));
1506 TPoint3D E3(eigenVect(2, 0), eigenVect(2, 1), eigenVect(2, 2));
1510 TPoint3D p1(center + E1 * eigenVal[0] * 100);
1511 TPoint3D p2(center + E2 * eigenVal[1] * 100);
1512 TPoint3D p3(center + E3 * eigenVal[2] * 100);
1515 center.
x, center.
y, center.
z, p1.
x, p1.
y, p1.
z);
1517 center.
x, center.
y, center.
z, p2.
x, p2.
y, p2.
z);
1519 center.
x, center.
y, center.
z, p3.
x, p3.
y, p3.
z);
1521 arrow1->setColor(
TColorf(0, 1, 0));
1522 arrow2->setColor(
TColorf(1, 0, 0));
1523 arrow3->setColor(
TColorf(0, 0, 1));
1525 scene->insert(arrow1);
1526 scene->insert(arrow2);
1527 scene->insert(arrow3);
1539 scene->insert(gl_points);
1546 gl_points->loadFromPointsMap(&pntsMap);
1558 void CFaceDetection::experimental_viewRegions(
1559 const vector<TPoint3D> regions[9],
const TPoint3D meanPos[3][3])
1574 gl_points->setPointSize(6);
1578 if (meanPos !=
nullptr)
1580 for (
size_t i = 0; i < 3; i++)
1581 for (
size_t j = 0; j < 3; j++)
1583 CSphere::Ptr sphere = std::make_shared<CSphere>(0.005f);
1584 sphere->setLocation(meanPos[i][j]);
1585 sphere->setColor(
TColorf(0, 1, 0));
1586 scene->insert(sphere);
1590 vector<TSegment3D> sgms;
1591 sgms.emplace_back(meanPos[0][0], meanPos[0][1]);
1592 sgms.emplace_back(meanPos[0][1], meanPos[0][2]);
1593 sgms.emplace_back(meanPos[1][0], meanPos[1][1]);
1594 sgms.emplace_back(meanPos[1][1], meanPos[1][2]);
1595 sgms.emplace_back(meanPos[2][0], meanPos[2][1]);
1596 sgms.emplace_back(meanPos[2][1], meanPos[2][2]);
1597 sgms.emplace_back(meanPos[0][0], meanPos[1][1]);
1598 sgms.emplace_back(meanPos[1][1], meanPos[2][2]);
1599 sgms.emplace_back(meanPos[2][0], meanPos[1][1]);
1600 sgms.emplace_back(meanPos[1][1], meanPos[0][2]);
1603 lines->setColor(0, 0, 1, 1);
1604 lines->setLineWidth(10);
1606 scene->insert(lines);
1608 scene->insert(gl_points);
1615 vector<float> xs, ys, zs;
1617 for (
size_t i = 0; i < 9; i++)
1618 for (
const auto& j : regions[i])
1628 float colors[9][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1},
1629 {1, 1, 0}, {1, 0, 1}, {0, 1, 1},
1630 {0.5f, 0.25f, 0}, {0.5f, 0, 0.25f}, {0, 0.35f, 0.5f}};
1631 for (
size_t i = 0; i < 9; i++)
1633 float R = colors[i][0];
1634 float G = colors[i][1];
1635 float B = colors[i][2];
1637 for (
unsigned int j = 0; j < regions[i].size(); j++, cont++)
1641 gl_points->loadFromPointsMap(&pntsMap);
1654 void CFaceDetection::experimental_segmentFace(
1660 region.
setSize(faceWidth, faceHeight,
true);
1662 unsigned int x1 = ceil(faceWidth * 0.4);
1663 unsigned int x2 = floor(faceWidth * 0.6);
1664 unsigned int y1 = ceil(faceHeight * 0.4);
1665 unsigned int y2 = floor(faceHeight * 0.6);
1667 region.
setSize(faceHeight, faceWidth);
1669 toExpand.
setSize(faceHeight, faceWidth,
true);
1671 unsigned int cont = (y1 <= 1 ? 0 : faceHeight * (y1 - 1));
1678 const Eigen::MatrixXf range2D =
1679 m_lastFaceDetected.rangeImage.asEigen().cast<
float>() *
1680 m_lastFaceDetected.rangeUnits * (1.0f / 5);
1684 for (
unsigned int i = y1; i <= y2; i++)
1688 for (
unsigned int j = x1; j <= x2; j++, cont++)
1691 m_options.confidenceThreshold)
1696 cont += faceWidth - x2;
1701 bool newExpanded =
true;
1705 newExpanded =
false;
1707 for (
size_t row = 0; row < faceHeight; row++)
1709 for (
size_t col = 0; col < faceWidth; col++)
1711 if (toExpand(row, col) == 1)
1713 region(row, col) =
true;
1715 int value = img.
at<uint8_t>(col, row);
1717 if ((row > 0) && (toExpand(row - 1, col) != 2))
1719 int value2 = img.
at<uint8_t>(col, row - 1);
1720 if (std::abs(value - value2) < 2)
1722 toExpand(row - 1, col) = 1;
1727 if ((row < faceWidth - 1) && (toExpand(row + 1, col) != 2))
1729 int value2 = img.
at<uint8_t>(col, row + 1);
1730 if (std::abs(value - value2) < 2)
1732 toExpand(row + 1, col) = 1;
1737 if ((col > 0) && (toExpand(row, col - 1) != 2))
1739 int value2 = img.
at<uint8_t>(col - 1, row);
1740 if (std::abs(value - value2) < 2)
1742 toExpand(row, col - 1) = 1;
1747 if ((col < faceHeight - 1) && (toExpand(row, col + 1) != 2))
1749 int value2 = img.
at<uint8_t>(col + 1, row);
1750 if (std::abs(value - value2) < 2)
1752 toExpand(row, col + 1) = 1;
1757 toExpand(row, col) = 2;
1763 for (
unsigned int row = 0; row < faceHeight; row++)
1765 for (
unsigned int col = 0; col < faceWidth; col++)
1767 if (!(region(row, col)))
1775 if (m_measure.faceNum >= 314)
1788 void CFaceDetection::experimental_calcHist(
1789 const CImage& face,
size_t c1,
size_t r1,
size_t c2,
size_t r2,
1794 for (
size_t row = r1; row <= r2; row++)
1795 for (
size_t col = c1; col <= c2; col++)
1797 auto value = face.
at<uint8_t>(col, row);
1798 int count = hist(0, value) + 1;
1799 hist(0, value) = count;
1807 void CFaceDetection::experimental_showMeasurements()
1814 f.open(
"statistics.txt", ofstream::app);
1816 if (m_measure.lessEigenVals.size() > 0)
1818 double meanEigenVal, stdEigenVal;
1819 double minEigenVal = *min_element(
1820 m_measure.lessEigenVals.begin(), m_measure.lessEigenVals.end());
1821 double maxEigenVal = *max_element(
1822 m_measure.lessEigenVals.begin(), m_measure.lessEigenVals.end());
1824 meanAndStd(m_measure.lessEigenVals, meanEigenVal, stdEigenVal);
1827 <<
"Statistical data about eigen values calculated of regions " 1830 cout <<
"Min eigenVal: " << minEigenVal << endl;
1831 cout <<
"Max eigenVal: " << maxEigenVal << endl;
1832 cout <<
"Mean eigenVal: " << meanEigenVal << endl;
1833 cout <<
"Standard Desv: " << stdEigenVal << endl;
1835 if (m_measure.saveMeasurementsToFile)
1838 <<
"Statistical data about eigen values calculated of regions " 1841 f <<
"Min eigenVal: " << minEigenVal << endl;
1842 f <<
"Max eigenVal: " << maxEigenVal << endl;
1843 f <<
"Mean eigenVal: " << meanEigenVal << endl;
1844 f <<
"Standard Desv: " << stdEigenVal << endl;
1848 if (m_measure.sumDistances.size() > 0)
1850 double meanSumDist, stdSumDist;
1851 double minSumDist = *min_element(
1852 m_measure.sumDistances.begin(), m_measure.sumDistances.end());
1853 double maxSumDist = *max_element(
1854 m_measure.sumDistances.begin(), m_measure.sumDistances.end());
1856 meanAndStd(m_measure.sumDistances, meanSumDist, stdSumDist);
1858 cout << endl <<
"Statistical data about sum of distances" << endl;
1859 cout <<
"Min sumDistances: " << minSumDist << endl;
1860 cout <<
"Max sumDistances: " << maxSumDist << endl;
1861 cout <<
"Mean sumDistances: " << meanSumDist << endl;
1862 cout <<
"Standard Desv: " << stdSumDist << endl;
1864 if (m_measure.saveMeasurementsToFile)
1866 f << endl <<
"Statistical data about sum of distances" << endl;
1867 f <<
"Min sumDistances: " << minSumDist << endl;
1868 f <<
"Max sumDistances: " << maxSumDist << endl;
1869 f <<
"Mean sumDistances: " << meanSumDist << endl;
1870 f <<
"Standard Desv: " << stdSumDist << endl;
1874 if (m_measure.errorEstimations.size() > 0)
1876 double meanEstimationErr, stdEstimationErr;
1877 double minEstimationErr = *min_element(
1878 m_measure.errorEstimations.begin(),
1879 m_measure.errorEstimations.end());
1880 double maxEstimationErr = *max_element(
1881 m_measure.errorEstimations.begin(),
1882 m_measure.errorEstimations.end());
1885 m_measure.errorEstimations, meanEstimationErr, stdEstimationErr);
1888 <<
"Statistical data about estimation error adjusting a plane of " 1889 "regions detected as faces" 1891 cout <<
"Min estimation: " << minEstimationErr << endl;
1892 cout <<
"Max estimation: " << maxEstimationErr << endl;
1893 cout <<
"Mean estimation: " << meanEstimationErr << endl;
1894 cout <<
"Standard Desv: " << stdEstimationErr << endl;
1896 if (m_measure.saveMeasurementsToFile)
1899 <<
"Statistical data about estimation error adjusting a plane of " 1900 "regions detected as faces" 1902 f <<
"Min estimation: " << minEstimationErr << endl;
1903 f <<
"Max estimation: " << maxEstimationErr << endl;
1904 f <<
"Mean estimation: " << meanEstimationErr << endl;
1905 f <<
"Standard Desv: " << stdEstimationErr << endl;
1909 cout << endl <<
"Data about number of faces" << endl;
1910 cout <<
"Possible faces detected: " << m_measure.numPossibleFacesDetected
1912 cout <<
"Real faces detected: " << m_measure.numRealFacesDetected << endl;
1914 if (m_meanHist.size() > 0)
1916 double minHist = *min_element(m_meanHist.begin(), m_meanHist.end());
1917 double maxHist = *max_element(m_meanHist.begin(), m_meanHist.end());
1922 cout << endl <<
"Mean hist: " << meanHist << endl;
1923 cout <<
"Min hist: " << minHist << endl;
1924 cout <<
"Max hist: " << maxHist << endl;
1925 cout <<
"Stdv: " << stdHist << endl;
1928 if (m_measure.saveMeasurementsToFile)
1930 f << endl <<
"Data about number of faces" << endl;
1931 f <<
"Possible faces detected: " << m_measure.numPossibleFacesDetected
1933 f <<
"Real faces detected: " << m_measure.numRealFacesDetected << endl;
1936 if (m_measure.takeTime && m_measure.saveMeasurementsToFile)
1937 f << endl << m_timeLog.getStatsAsText();
1948 void CFaceDetection::debug_returnResults(
1950 const std::vector<uint32_t>& ignore,
unsigned int& falsePositivesDeleted,
1951 unsigned int& realFacesDeleted)
1953 const unsigned int numDeleted = m_measure.deletedRegions.size();
1955 const unsigned int numIgnored = ignore.size();
1956 unsigned int ignoredDetected = 0;
1958 falsePositivesDeleted = 0;
1960 for (
unsigned int i = 0; i < numDeleted; i++)
1962 unsigned int region = m_measure.deletedRegions[i];
1964 bool falsePositive =
false;
1967 while (!falsePositive && (j < numFalsePositives))
1974 falsePositivesDeleted++;
1980 while (!igno && (j < numIgnored))
1982 if (region == ignore[j]) igno =
true;
1986 if (igno) ignoredDetected++;
1990 realFacesDeleted = numDeleted - falsePositivesDeleted - ignoredDetected;
1992 m_measure.faceNum = 0;
1993 m_measure.deletedRegions.clear();
bool eig(Derived &eVecs, std::vector< Scalar > &eVals, bool sorted=true) const
Computes the eigenvectors and eigenvalues for a square, general matrix.
void unlockAccess3DScene()
Unlocks the access to the internal 3D scene.
A compile-time fixed-size numeric matrix container.
void thread_checkIfDiagonalSurface()
static Ptr Create(Args &&... args)
#define MRPT_TRY_END
The end of a standard MRPT "try...catch()" block that allows tracing throw the call stack after an ex...
void setWindowTitle(const std::string &str) override
Changes the window title.
size_t size(const MATRIXLIKE &m, const int dim)
mrpt::opengl::COpenGLScene::Ptr & get3DSceneAndLock()
Gets a reference to the smart shared pointer that holds the internal scene (carefuly read introductio...
void resize(unsigned int width, unsigned int height) override
Resizes the window, stretching the image to fit into the display area.
void setCameraPointingToPoint(float x, float y, float z)
Changes the camera parameters programmatically.
This file implements several operations that operate element-wise on individual or pairs of container...
A range or depth 3D scan measurement, as from a time-of-flight range camera or a structured-light dep...
size_t getHeight() const override
Returns the height of the image in pixels.
const T & at(unsigned int col, unsigned int row, unsigned int channel=0) const
Access to pixels without checking boundaries, and doing a reinterpret_cast<> of the data as the given...
std::vector< CDetectableObject::Ptr > vector_detectable_object
static Ptr Create(Args &&... args)
void getSize(TImageSize &s) const
Return the size of the image.
int read_int(const std::string §ion, const std::string &name, int defaultValue, bool failIfNotFound=false) const
std::vector< float > points3D_z
vector< std::vector< uint32_t > > falsePositives
#define MRPT_TRY_START
The start of a standard MRPT "try...catch()" block that allows tracing throw the call stack after an ...
This class allows loading and storing values and vectors of different types from a configuration text...
This base provides a set of functions for maths stuff.
size_t getWidth() const override
Returns the width of the image in pixels.
std::vector< float > points3D_y
void setAllPoints(const std::vector< float > &X, const std::vector< float > &Y, const std::vector< float > &Z)
Set all the points at once from vectors with X,Y and Z coordinates.
This class creates a window as a graphical user interface (GUI) for displaying images to the user...
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
mrpt::img::CImage intensityImage
If hasIntensityImage=true, a color or gray-level intensity image of the same size than "rangeImage"...
A pair (x,y) of pixel coordinates (integer resolution).
This namespace contains representation of robot actions and observations.
3D Plane, represented by its equation
void thread_checkIfFaceRegions()
void setFromMatrix(const MAT &m, bool matrix_is_normalized=true)
Set the image from a matrix, interpreted as grayscale intensity values, in the range [0...
#define IS_CLASS(obj, class_name)
True if the given reference to object (derived from mrpt::rtti::CObject) is of the given class...
double getRegressionPlane(const std::vector< TPoint3D > &points, TPlane &plane)
Using eigenvalues, gets the best fitting plane for a set of 3D points.
TPoint3D_< double > TPoint3D
Lightweight 3D point.
double read_double(const std::string §ion, const std::string &name, double defaultValue, bool failIfNotFound=false) const
void thread_checkIfFacePlaneCov()
Specific class for face detection.
A map of 2D/3D points with individual colours (RGB).
CMatrixDouble cov(const MATRIX &v)
Computes the covariance matrix from a list of samples in an NxM matrix, where each row is a sample...
mrpt::img::CImage confidenceImage
If hasConfidenceImage=true, an image with the "confidence" value [range 0-255] as estimated by the ca...
mrpt::gui::CDisplayWindow3D::Ptr win
size_type rows() const
Number of rows in the matrix.
size_type cols() const
Number of columns in the matrix.
void pause(const std::string &msg=std::string("Press any key to continue...")) noexcept
Shows the message "Press any key to continue" (or other custom message) to the current standard outpu...
void setPixel(int x, int y, size_t color) override
Changes the value of the pixel (x,y).
const_iterator end() const
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void meanAndStd(const VECTORLIKE &v, double &out_mean, double &out_std, bool unbiased=true)
Computes the standard deviation of a vector (or all elements of a matrix)
Declares a class that represents any robot's observation.
bool read_bool(const std::string §ion, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
void setSize(size_t row, size_t col, bool zeroNewElements=false)
Changes the size of matrix, maintaining the previous contents.
An RGBA color - floats in the range [0,1].
void setCameraZoom(float zoom)
Changes the camera parameters programmatically.
std::vector< float > points3D_x
If hasPoints3D=true, the (X,Y,Z) coordinates of the 3D point cloud detected by the camera...
The namespace for 3D scene representation and rendering.
T distanceTo(const TPoint3D_< T > &p) const
Point-to-point distance.
Classes for creating GUI windows for 2D and 3D visualization.
void repaint()
Repaints the window.
This template class provides the basic functionality for a general 2D any-size, resizable container o...
static Ptr Create(Args &&... args)
double distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.
static Ptr Create(Args &&... args)
void setCameraAzimuthDeg(float deg)
Changes the camera parameters programmatically.
void setPointColor(size_t index, float R, float G, float B)
Changes just the color of a given point from the map.
A class for storing images as grayscale or RGB bitmaps.
bool hasConfidenceImage
true means the field confidenceImage contains valid data
void setCameraElevationDeg(float deg)
Changes the camera parameters programmatically.
A graphical user interface (GUI) for efficiently rendering 3D scenes in real-time.