8 #ifndef META_OCEAN_GEOMETRY_ERROR_H
9 #define META_OCEAN_GEOMETRY_ERROR_H
33 class OCEAN_GEOMETRY_EXPORT
Error
68 inline ErrorElement(
const unsigned int imageIndex,
const unsigned int candidateIndex,
const Scalar error);
74 inline unsigned int imageIndex()
const;
80 inline unsigned int candidateIndex()
const;
86 inline Scalar error()
const;
93 inline bool operator<(
const ErrorElement& element)
const;
98 unsigned int imageIndex_ = (
unsigned int)(-1);
101 unsigned int candidateIndex_ = (
unsigned int)(-1);
257 template <
typename TAccessorImagePo
ints,
bool tResultingErrors,
bool tResultingSqrErrors>
258 static Scalar determineHomographyError(
const SquareMatrix3& points1_H_points0,
const TAccessorImagePoints& imagePointAccessor0,
const TAccessorImagePoints& imagePointAccessor1,
Vector2* errors =
nullptr,
Scalar* sqrErrors =
nullptr);
328 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tUseBorderDistortionIfOuts
ide,
bool tResultingErrors,
bool tResultingSqrErrors>
329 static inline Scalar determinePoseError(
const HomogenousMatrix4& world_T_camera,
const PinholeCamera& pinholeCamera,
const TAccessorObjectPoints& objectPointAccessor,
const TAccessorImagePoints& imagePointAccessor,
const bool useDistortionParameters,
const Scalar zoom =
Scalar(1),
Vector2* errors =
nullptr,
Scalar* sqrErrors =
nullptr);
346 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tResultingErrors,
bool tResultingSqrErrors>
347 static Scalar determinePoseError(
const HomogenousMatrix4& world_T_camera,
const AnyCamera& anyCamera,
const TAccessorObjectPoints& objectPointAccessor,
const TAccessorImagePoints& imagePointAccessor,
Vector2* errors =
nullptr,
Scalar* sqrErrors =
nullptr);
367 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tUseBorderDistortionIfOuts
ide,
bool tResultingErrors,
bool tResultingSqrErrors>
368 static Scalar determinePoseErrorIF(
const HomogenousMatrix4& flippedCamera_T_world,
const PinholeCamera& pinholeCamera,
const TAccessorObjectPoints& objectPointAccessor,
const TAccessorImagePoints& imagePointAccessor,
const bool useDistortionParameters,
const Scalar zoom =
Scalar(1),
Vector2* errors =
nullptr,
Scalar* sqrErrors =
nullptr);
385 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tResultingErrors,
bool tResultingSqrErrors>
386 static Scalar determinePoseErrorIF(
const HomogenousMatrix4& flippedCamera_T_world,
const AnyCamera& anyCamera,
const TAccessorObjectPoints& objectPointAccessor,
const TAccessorImagePoints& imagePointAccessor,
Vector2* errors =
nullptr,
Scalar* sqrErrors =
nullptr);
403 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tOnlyFrontObjectPo
ints>
404 [[nodiscard]]
static inline bool determinePoseError(
const HomogenousMatrix4& world_T_camera,
const AnyCamera& camera,
const TAccessorObjectPoints& objectPointAccessor,
const TAccessorImagePoints& imagePointAccessor,
Scalar& sqrAveragePixelError,
Scalar& sqrMinimalPixelError,
Scalar& sqrMaximalPixelError);
421 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints>
422 static inline void determinePoseError(
const HomogenousMatrix4& world_T_camera,
const AnyCamera& camera,
const TAccessorObjectPoints& objectPointAccessor,
const TAccessorImagePoints& imagePointAccessor,
Scalar& sqrAveragePixelError,
Scalar& sqrMinimalPixelError,
Scalar& sqrMaximalPixelError);
440 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tUseBorderDistortionIfOuts
ide>
441 static inline void determinePoseError(
const HomogenousMatrix4& world_T_camera,
const PinholeCamera& pinholeCamera,
const TAccessorObjectPoints& objectPointAccessor,
const TAccessorImagePoints& imagePointAccessor,
const bool useDistortionParameters,
Scalar& sqrAveragePixelError,
Scalar& sqrMinimalPixelError,
Scalar& sqrMaximalPixelError,
const Scalar zoom =
Scalar(1));
458 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tOnlyFrontObjectPo
ints>
459 [[nodiscard]]
static bool determinePoseErrorIF(
const HomogenousMatrix4& flippedCamera_T_world,
const AnyCamera& camera,
const TAccessorObjectPoints& objectPointAccessor,
const TAccessorImagePoints& imagePointAccessor,
Scalar& sqrAveragePixelError,
Scalar& sqrMinimalPixelError,
Scalar& sqrMaximalPixelError);
476 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints>
477 static void determinePoseErrorIF(
const HomogenousMatrix4& flippedCamera_T_world,
const AnyCamera& camera,
const TAccessorObjectPoints& objectPointAccessor,
const TAccessorImagePoints& imagePointAccessor,
Scalar& sqrAveragePixelError,
Scalar& sqrMinimalPixelError,
Scalar& sqrMaximalPixelError);
497 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tUseBorderDistortionIfOuts
ide>
498 static void determinePoseErrorIF(
const HomogenousMatrix4& flippedCamera_T_world,
const PinholeCamera& pinholeCamera,
const TAccessorObjectPoints& objectPointAccessor,
const TAccessorImagePoints& imagePointAccessor,
const bool useDistortionParameters,
Scalar& sqrAveragePixelError,
Scalar& sqrMinimalPixelError,
Scalar& sqrMaximalPixelError,
const Scalar zoom =
Scalar(1));
514 template <Estimator::EstimatorType tEstimator>
515 static Scalar averagedRobustErrorInPointCloud(
const Vector2* imagePoints,
const size_t numberImagePoints,
const size_t validImagePoints,
const Vector2* candidatePoints,
const size_t numberCandidatePoints,
const ErrorDetermination errorDetermination,
IndexPairs32* correspondences =
nullptr);
535 template <Estimator::EstimatorType tEstimator>
536 static Scalar uniqueAveragedRobustErrorInPointCloud(
const Vector2* imagePoints,
const size_t numberImagePoints,
const size_t validImagePoints,
const Vector2* candidatePoints,
const size_t numberCandidatePoints,
IndexPairs32* correspondences =
nullptr);
556 template <Estimator::EstimatorType tEstimator>
557 static Scalar approximatedAveragedRobustErrorInPointCloud(
const Vector2* imagePoints,
const size_t numberImagePoints,
const size_t validImagePoints,
const Vector2* candidatePoints,
const size_t numberCandidatePoints,
IndexPairs32* correspondences =
nullptr);
577 template <Estimator::EstimatorType tEstimator>
578 static Scalar ambiguousAveragedRobustErrorInPointCloud(
const Vector2* imagePoints,
const size_t numberImagePoints,
const size_t validImagePoints,
const Vector2* candidatePoints,
const size_t numberCandidatePoints,
IndexPairs32* correspondences =
nullptr);
588 template <Estimator::EstimatorType tEstimator>
589 static Scalar averagedRobustError(
const Scalar* sqrErrors,
const size_t number,
const Scalar* explicitWeights =
nullptr);
611 template <Estimator::EstimatorType tEstimator>
612 static Scalar averagedRobustError(
const Scalar* sqrErrors,
const unsigned int* indices,
const size_t numberIndices,
const Scalar* explicitWeights =
nullptr);
624 static inline Scalar averagedRobustError(
const Scalar* sqrErrors,
const unsigned int* indices,
const size_t numberIndices,
const Estimator::EstimatorType estimator,
const Scalar* explicitWeights =
nullptr);
628 imageIndex_(imageIndex),
629 candidateIndex_(candidateIndex),
642 return candidateIndex_;
652 return error_ < element.
error_;
660 return Numeric::abs(poseFirstPosition.
x() - poseSecondPosition.
x()) <= maxTranslationOffset.
x()
661 &&
Numeric::abs(poseFirstPosition.
y() - poseSecondPosition.
y()) <= maxTranslationOffset.
y()
662 &&
Numeric::abs(poseFirstPosition.
z() - poseSecondPosition.
z()) <= maxTranslationOffset.
z();
672 return poseFirstOrientation.
cos2(poseSecondOrientation) >= maxOrientationOffsetCos2;
675 template <
typename TAccessorImagePo
ints,
bool tResultingErrors,
bool tResultingSqrErrors>
678 ocean_assert(imagePointAccessor0.size() == imagePointAccessor1.size());
680 if (imagePointAccessor0.isEmpty())
685 ocean_assert((tResultingErrors && errors !=
nullptr) || (!tResultingErrors && errors ==
nullptr));
686 ocean_assert((tResultingSqrErrors && sqrErrors !=
nullptr) || (!tResultingSqrErrors && sqrErrors ==
nullptr));
688 ocean_assert(!points1_H_points0.
isSingular());
690 Scalar sqrAveragePixelError = 0;
692 for (
size_t n = 0; n < imagePointAccessor0.size(); ++n)
696 if (points1_H_points0.
multiply(imagePointAccessor0[n], transformedPoint))
698 const Vector2& measuredPoint = imagePointAccessor1[n];
700 const Vector2 difference(transformedPoint - measuredPoint);
701 const Scalar sqrPixelError = difference.
sqr();
703 sqrAveragePixelError += sqrPixelError;
705 if constexpr (tResultingErrors)
707 errors[n] = difference;
710 if constexpr (tResultingSqrErrors)
712 sqrErrors[n] = sqrPixelError;
717 if constexpr (tResultingErrors)
722 if constexpr (tResultingSqrErrors)
731 ocean_assert(imagePointAccessor0.size() != 0);
732 ocean_assert(sqrAveragePixelError >= 0 && sqrAveragePixelError <=
Numeric::maxValue());
734 return sqrAveragePixelError /
Scalar(imagePointAccessor0.size());
737 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tUseBorderDistortionIfOuts
ide,
bool tResultingErrors,
bool tResultingSqrErrors>
740 return determinePoseErrorIF<TAccessorObjectPoints, TAccessorImagePoints, tUseBorderDistortionIfOutside, tResultingErrors, tResultingSqrErrors>(
PinholeCamera::standard2InvertedFlipped(world_T_camera), pinholeCamera, objectPointAccessor, imagePointAccessor, useDistortionParameters, zoom, errors, sqrErrors);
743 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tResultingErrors,
bool tResultingSqrErrors>
746 return determinePoseErrorIF<TAccessorObjectPoints, TAccessorImagePoints, tResultingErrors, tResultingSqrErrors>(
PinholeCamera::standard2InvertedFlipped(world_T_camera), anyCamera, objectPointAccessor, imagePointAccessor, errors, sqrErrors);
749 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tOnlyFrontObjectPo
ints>
752 return determinePoseErrorIF<TAccessorObjectPoints, TAccessorImagePoints, tOnlyFrontObjectPoints>(
AnyCamera::standard2InvertedFlipped(world_T_camera), camera, objectPointAccessor, imagePointAccessor, sqrAveragePixelError, sqrMinimalPixelError,sqrMaximalPixelError);
755 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints>
758 determinePoseErrorIF<TAccessorObjectPoints, TAccessorImagePoints>(
AnyCamera::standard2InvertedFlipped(world_T_camera), camera, objectPointAccessor, imagePointAccessor, sqrAveragePixelError, sqrMinimalPixelError,sqrMaximalPixelError);
761 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tUseBorderDistortionIfOuts
ide>
764 determinePoseErrorIF<TAccessorObjectPoints, TAccessorImagePoints, tUseBorderDistortionIfOutside>(
PinholeCamera::standard2InvertedFlipped(world_T_camera), pinholeCamera, objectPointAccessor, imagePointAccessor, useDistortionParameters, sqrAveragePixelError, sqrMinimalPixelError,sqrMaximalPixelError, zoom);
774 return camera.
projectToImageIF(flippedCamera_T_world, objectPoint) - imagePoint;
784 return pinholeCamera.
projectToImageIF<
true>(flippedCamera_T_world, objectPoint, useDistortionParameters) - imagePoint;
787 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tUseBorderDistortionIfOuts
ide,
bool tResultingErrors,
bool tResultingSqrErrors>
790 ocean_assert(flippedCamera_T_world.
isValid());
791 ocean_assert(objectPointAccessor.size() == imagePointAccessor.size());
792 ocean_assert((tResultingErrors && errors !=
nullptr) || (!tResultingErrors && errors ==
nullptr));
793 ocean_assert((tResultingSqrErrors && sqrErrors !=
nullptr) || (!tResultingSqrErrors && sqrErrors ==
nullptr));
796 if (objectPointAccessor.isEmpty())
801 Scalar sqrAveragePixelError = 0;
805 for (
size_t n = 0; n < objectPointAccessor.size(); ++n)
807 const Vector2 imagePoint(pinholeCamera.
projectToImageIF<
true, tUseBorderDistortionIfOutside>(flippedCamera_T_world, objectPointAccessor[n], zoom));
808 const Vector2& measuredImagePoint = imagePointAccessor[n];
810 const Vector2 difference(imagePoint - measuredImagePoint);
811 const Scalar sqrPixelError = difference.
sqr();
813 sqrAveragePixelError += sqrPixelError;
815 if constexpr (tResultingErrors)
817 errors[n] = difference;
820 if constexpr (tResultingSqrErrors)
822 sqrErrors[n] = sqrPixelError;
833 debugCameraMatrix(0, 0) *= zoom;
834 debugCameraMatrix(1, 1) *= zoom;
835 debugCameraMatrix[15] = 1;
840 ocean_assert(transformationMatrixIF == debugTransformationMatrixIF);
843 for (
size_t n = 0; n < objectPointAccessor.size(); ++n)
845 const Vector3 transformedObjectPoint(transformationMatrixIF * objectPointAccessor[n]);
848 const Scalar factor =
Scalar(1) / transformedObjectPoint.
z();
850 const Vector2 imagePoint(transformedObjectPoint.
x() * factor, transformedObjectPoint.
y() * factor);
852 const Vector2 difference(imagePoint - imagePointAccessor[n]);
853 const Scalar sqrPixelError = difference.
sqr();
855 sqrAveragePixelError += sqrPixelError;
857 if constexpr (tResultingErrors)
859 errors[n] = difference;
862 if constexpr (tResultingSqrErrors)
864 sqrErrors[n] = sqrPixelError;
869 ocean_assert(objectPointAccessor.size() != 0);
870 return sqrAveragePixelError /
Scalar(objectPointAccessor.size());
873 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tResultingErrors,
bool tResultingSqrErrors>
876 ocean_assert(flippedCamera_T_world.
isValid() && anyCamera.
isValid());
877 ocean_assert(objectPointAccessor.size() == imagePointAccessor.size());
879 ocean_assert((tResultingErrors && errors !=
nullptr) || (!tResultingErrors && errors ==
nullptr));
880 ocean_assert((tResultingSqrErrors && sqrErrors !=
nullptr) || (!tResultingSqrErrors && sqrErrors ==
nullptr));
882 if (objectPointAccessor.isEmpty())
887 Scalar sqrAveragePixelError = 0;
889 for (
size_t n = 0; n < objectPointAccessor.size(); ++n)
893 const Vector2& measuredImagePoint = imagePointAccessor[n];
895 const Vector2 difference(imagePoint - measuredImagePoint);
896 const Scalar sqrPixelError = difference.
sqr();
898 sqrAveragePixelError += sqrPixelError;
900 if constexpr (tResultingErrors)
902 errors[n] = difference;
905 if constexpr (tResultingSqrErrors)
907 sqrErrors[n] = sqrPixelError;
911 ocean_assert(objectPointAccessor.size() != 0);
912 return sqrAveragePixelError /
Scalar(objectPointAccessor.size());
915 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tOnlyFrontObjectPo
ints>
918 ocean_assert(flippedCamera_T_world.
isValid());
919 ocean_assert(objectPointAccessor.size() == imagePointAccessor.size());
921 sqrAveragePixelError = 0;
923 sqrMaximalPixelError = 0;
925 if (objectPointAccessor.isEmpty())
930 for (
size_t n = 0; n < objectPointAccessor.size(); ++n)
932 const Vector3& objectPoint = objectPointAccessor[n];
934 if constexpr (tOnlyFrontObjectPoints)
943 const Vector2& imagePoint = imagePointAccessor[n];
947 sqrAveragePixelError += pixelError;
949 if (pixelError < sqrMinimalPixelError)
951 sqrMinimalPixelError = pixelError;
954 if (pixelError > sqrMaximalPixelError)
956 sqrMaximalPixelError = pixelError;
960 ocean_assert(objectPointAccessor.size() != 0);
961 sqrAveragePixelError /=
Scalar(objectPointAccessor.size());
967 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints>
970 constexpr
bool tOnlyFrontObjectPoints =
false;
972 const bool result = determinePoseErrorIF<TAccessorObjectPoints, TAccessorImagePoints, tOnlyFrontObjectPoints>(flippedCamera_T_world, camera, objectPointAccessor, imagePointAccessor, sqrAveragePixelError, sqrMinimalPixelError, sqrMaximalPixelError);
973 ocean_assert_and_suppress_unused(result, result);
976 template <
typename TAccessorObjectPo
ints,
typename TAccessorImagePo
ints,
bool tUseBorderDistortionIfOuts
ide>
979 ocean_assert(flippedCamera_T_world.
isValid());
980 ocean_assert(objectPointAccessor.size() == imagePointAccessor.size());
983 sqrAveragePixelError = 0;
985 sqrMaximalPixelError = 0;
987 if (objectPointAccessor.isEmpty())
994 for (
size_t n = 0; n < objectPointAccessor.size(); ++n)
996 const Vector2 imagePoint(pinholeCamera.
projectToImageIF<tUseBorderDistortionIfOutside>(flippedCamera_T_world, objectPointAccessor[n], useDistortionParameters, zoom));
997 const Vector2& realImagePoint = imagePointAccessor[n];
1001 sqrAveragePixelError += pixelError;
1003 if (pixelError < sqrMinimalPixelError)
1005 sqrMinimalPixelError = pixelError;
1008 if (pixelError > sqrMaximalPixelError)
1010 sqrMaximalPixelError = pixelError;
1021 debugCameraMatrix(0, 0) *= zoom;
1022 debugCameraMatrix(1, 1) *= zoom;
1023 debugCameraMatrix[15] = 1;
1028 ocean_assert(transformationMatrixIF == debugTransformationMatrixIF);
1031 for (
size_t n = 0; n < objectPointAccessor.size(); ++n)
1033 const Vector3 transformedObjectPoint(transformationMatrixIF * objectPointAccessor[n]);
1036 const Scalar factor =
Scalar(1) / transformedObjectPoint.
z();
1038 const Vector2 imagePoint(transformedObjectPoint.
x() * factor, transformedObjectPoint.
y() * factor);
1042 sqrAveragePixelError += pixelError;
1044 if (pixelError < sqrMinimalPixelError)
1046 sqrMinimalPixelError = pixelError;
1049 if (pixelError > sqrMaximalPixelError)
1051 sqrMaximalPixelError = pixelError;
1056 ocean_assert(objectPointAccessor.size() != 0);
1057 sqrAveragePixelError /=
Scalar(objectPointAccessor.size());
1060 template <Estimator::EstimatorType tEstimator>
1063 ocean_assert(imagePoints && candidatePoints);
1064 ocean_assert(numberImagePoints <= numberCandidatePoints);
1065 ocean_assert(validImagePoints <= numberImagePoints);
1067 switch (errorDetermination)
1070 return uniqueAveragedRobustErrorInPointCloud<tEstimator>(imagePoints, numberImagePoints, validImagePoints, candidatePoints, numberCandidatePoints, correspondences);
1073 return approximatedAveragedRobustErrorInPointCloud<tEstimator>(imagePoints, numberImagePoints, validImagePoints, candidatePoints, numberCandidatePoints, correspondences);
1076 return ambiguousAveragedRobustErrorInPointCloud<tEstimator>(imagePoints, numberImagePoints, validImagePoints, candidatePoints, numberCandidatePoints, correspondences);
1082 ocean_assert(
false &&
"Invalid errorDetermination parameter!");
1086 template <Estimator::EstimatorType tEstimator>
1089 ocean_assert(imagePoints && candidatePoints);
1090 ocean_assert(numberImagePoints <= numberCandidatePoints);
1091 ocean_assert(validImagePoints <= numberImagePoints);
1093 if (numberImagePoints > numberCandidatePoints)
1097 errorElements.reserve(numberImagePoints * numberCandidatePoints);
1099 for (
unsigned int i = 0; i < numberImagePoints; ++i)
1101 const Vector2& imagePoint(imagePoints[i]);
1103 for (
unsigned int c = 0; c < numberCandidatePoints; ++c)
1109 std::sort(errorElements.begin(), errorElements.end());
1111 std::vector<unsigned char> usedImagePoints(numberImagePoints, 0u);
1112 std::vector<unsigned char> usedCandidatePoints(numberCandidatePoints, 0u);
1114 if constexpr (Estimator::isStandardEstimator<tEstimator>())
1116 size_t numberUsedErrors = 0;
1119 ErrorElements::const_iterator i = errorElements.begin();
1120 while (i != errorElements.end() && numberUsedErrors < validImagePoints)
1122 ocean_assert(i != errorElements.end());
1124 if (usedImagePoints[i->imageIndex()] == 0u && usedCandidatePoints[i->candidateIndex()] == 0u)
1126 sqrErrors += i->error();
1129 usedImagePoints[i->imageIndex()] = 1u;
1130 usedCandidatePoints[i->candidateIndex()] = 1u;
1132 if (correspondences)
1134 correspondences->push_back(
IndexPair32(i->imageIndex(), i->candidateIndex()));
1141 if (numberUsedErrors == 0)
1146 return sqrErrors /
Scalar(numberUsedErrors);
1151 sqrErrors.reserve(validImagePoints);
1153 ErrorElements::const_iterator i = errorElements.begin();
1154 while (i != errorElements.end() && sqrErrors.size() < validImagePoints)
1156 ocean_assert(i != errorElements.end());
1158 if (usedImagePoints[i->imageIndex()] == 0u && usedCandidatePoints[i->candidateIndex()] == 0u)
1160 sqrErrors.push_back(i->error());
1162 usedImagePoints[i->imageIndex()] = 1u;
1163 usedCandidatePoints[i->candidateIndex()] = 1u;
1165 if (correspondences)
1167 correspondences->push_back(
IndexPair32(i->imageIndex(), i->candidateIndex()));
1174 if (sqrErrors.empty())
1179 const size_t numberUsedErrors = min(validImagePoints, sqrErrors.size());
1181 return averagedRobustError<tEstimator>(sqrErrors.data(), numberUsedErrors);
1185 template <Estimator::EstimatorType tEstimator>
1188 if (validImagePoints == 0)
1191 ocean_assert(imagePoints && candidatePoints);
1192 ocean_assert(numberImagePoints <= numberCandidatePoints);
1193 ocean_assert(validImagePoints <= numberImagePoints);
1195 if (numberImagePoints > numberCandidatePoints)
1201 errorElements.reserve(numberImagePoints);
1203 std::vector<unsigned char> usedCandidates(numberCandidatePoints, 0u);
1205 for (
unsigned int i = 0u; i < numberImagePoints; ++i)
1207 const Vector2& imagePoint(imagePoints[i]);
1210 unsigned int minIndex = 0xFFFFFFFF;
1212 for (
unsigned int c = 0u; c < numberCandidatePoints; ++c)
1214 if (usedCandidates[c] == 0u)
1218 if (value < minValue)
1226 ocean_assert(minIndex != 0xFFFFFFFF);
1228 errorElements.push_back(
ErrorElement(i, minIndex, minValue));
1230 ocean_assert(usedCandidates[minIndex] == 0u);
1231 usedCandidates[minIndex] = 1u;
1234 std::sort(errorElements.begin(), errorElements.end());
1236 ocean_assert(!errorElements.empty());
1238 if (errorElements.empty())
1243 const size_t numberUsedErrors = min(validImagePoints, errorElements.size());
1245 if constexpr (Estimator::isStandardEstimator<tEstimator>())
1249 if (correspondences)
1251 for (
size_t n = 0; n < numberUsedErrors; ++n)
1253 sqrErrors += errorElements[n].error();
1254 correspondences->push_back(
IndexPair32(errorElements[n].imageIndex(), errorElements[n].candidateIndex()));
1259 for (
size_t n = 0; n < numberUsedErrors; ++n)
1261 sqrErrors += errorElements[n].error();
1265 return sqrErrors /
Scalar(numberUsedErrors);
1270 sqrErrors.reserve(numberUsedErrors);
1272 for (
unsigned int n = 0; n < numberUsedErrors; ++n)
1274 sqrErrors.push_back(errorElements[n].error());
1276 if (correspondences)
1278 correspondences->push_back(
IndexPair32(errorElements[n].imageIndex(), errorElements[n].candidateIndex()));
1282 return averagedRobustError<tEstimator>(sqrErrors.data(), numberUsedErrors);
1286 template <Estimator::EstimatorType tEstimator>
1289 ocean_assert(imagePoints && candidatePoints);
1290 ocean_assert(numberImagePoints <= numberCandidatePoints);
1291 ocean_assert(validImagePoints <= numberImagePoints);
1293 if (numberImagePoints > numberCandidatePoints)
1298 if (numberImagePoints == 0)
1304 errorElements.reserve(numberImagePoints);
1306 for (
unsigned int i = 0; i < numberImagePoints; ++i)
1308 const Vector2& imagePoint(imagePoints[i]);
1311 unsigned int minIndex = 0xFFFFFFFF;
1313 for (
unsigned int c = 0; c < numberCandidatePoints; ++c)
1317 if (value < minValue)
1324 ocean_assert(minIndex != 0xFFFFFFFF);
1326 errorElements.push_back(
ErrorElement(i, minIndex, minValue));
1329 std::sort(errorElements.begin(), errorElements.end());
1331 ocean_assert(!errorElements.empty());
1333 if (errorElements.empty())
1338 const size_t numberUsedErrors = min(validImagePoints, errorElements.size());
1340 if constexpr (!Estimator::isStandardEstimator<tEstimator>())
1344 if (correspondences)
1346 for (
unsigned int n = 0; n < numberUsedErrors; ++n)
1348 sqrErrors += errorElements[n].error();
1349 correspondences->push_back(
IndexPair32(errorElements[n].imageIndex(), errorElements[n].candidateIndex()));
1354 for (
unsigned int n = 0; n < numberUsedErrors; ++n)
1356 sqrErrors += errorElements[n].error();
1360 return sqrErrors /
Scalar(numberUsedErrors);
1365 sqrErrors.reserve(numberUsedErrors);
1367 if (correspondences)
1369 for (
unsigned int n = 0; n < numberUsedErrors; ++n)
1371 sqrErrors.push_back(errorElements[n].error());
1372 correspondences->push_back(
IndexPair32(errorElements[n].imageIndex(), errorElements[n].candidateIndex()));
1377 for (
unsigned int n = 0; n < numberUsedErrors; ++n)
1379 sqrErrors.push_back(errorElements[n].error());
1383 return Geometry::Error::averagedRobustError<tEstimator>(sqrErrors.data(), numberUsedErrors);
1387 template <Estimator::EstimatorType tEstimator>
1390 ocean_assert(sqrErrors);
1391 ocean_assert(number > 0);
1399 const Scalar sqrSigma = Estimator::needSigma<tEstimator>() ?
Numeric::sqr(Estimator::determineSigmaSquare<tEstimator>(sqrErrors, number, 6)) : 0;
1403 if (explicitWeights)
1405 const Scalar*
const sqrErrorsEnd = sqrErrors + number;
1406 while (sqrErrors != sqrErrorsEnd)
1408 summedError += Estimator::robustErrorSquare<tEstimator>(*sqrErrors++, sqrSigma) * *explicitWeights++;
1413 const Scalar*
const sqrErrorsEnd = sqrErrors + number;
1414 while (sqrErrors != sqrErrorsEnd)
1416 summedError += Estimator::robustErrorSquare<tEstimator>(*sqrErrors++, sqrSigma);
1420 return summedError /
Scalar(number);
1428 return averagedRobustError<Estimator::ET_SQUARE>(sqrErrors, number, explicitWeights);
1431 return averagedRobustError<Estimator::ET_LINEAR>(sqrErrors, number, explicitWeights);
1434 return averagedRobustError<Estimator::ET_HUBER>(sqrErrors, number, explicitWeights);
1437 return averagedRobustError<Estimator::ET_CAUCHY>(sqrErrors, number, explicitWeights);
1440 return averagedRobustError<Estimator::ET_TUKEY>(sqrErrors, number, explicitWeights);
1446 ocean_assert(
false &&
"Invalid estimator type!");
1447 return averagedRobustError<Estimator::ET_SQUARE>(sqrErrors, number, explicitWeights);
1450 template <Estimator::EstimatorType tEstimator>
1453 ocean_assert(sqrErrors);
1454 ocean_assert(numberIndices > 0);
1456 if (numberIndices == 0)
1462 const Scalar sqrSigma = Estimator::needSigma<tEstimator>() ?
Numeric::sqr(Estimator::determineSigmaSquare<tEstimator>(sqrErrors, indices, numberIndices, 6)) : 0;
1466 if (explicitWeights)
1468 const Scalar*
const sqrErrorsEnd = sqrErrors + numberIndices;
1469 while (sqrErrors != sqrErrorsEnd)
1471 const unsigned int index = *indices++;
1472 summedError += Estimator::robustErrorSquare<tEstimator>(sqrErrors[index], sqrSigma) * explicitWeights[index];
1477 const Scalar*
const sqrErrorsEnd = sqrErrors + numberIndices;
1478 while (sqrErrors != sqrErrorsEnd)
1480 summedError += Estimator::robustErrorSquare<tEstimator>(sqrErrors[*indices++], sqrSigma);
1484 return summedError /
Scalar(numberIndices);
1492 return averagedRobustError<Estimator::ET_SQUARE>(sqrErrors, indices, numberIndices, explicitWeights);
1495 return averagedRobustError<Estimator::ET_LINEAR>(sqrErrors, indices, numberIndices, explicitWeights);
1498 return averagedRobustError<Estimator::ET_HUBER>(sqrErrors, indices, numberIndices, explicitWeights);
1501 return averagedRobustError<Estimator::ET_CAUCHY>(sqrErrors, indices, numberIndices, explicitWeights);
1504 return averagedRobustError<Estimator::ET_TUKEY>(sqrErrors, indices, numberIndices, explicitWeights);
1510 ocean_assert(
false &&
"Invalid estimator type!");
1511 return averagedRobustError<Estimator::ET_SQUARE>(sqrErrors, indices, numberIndices, explicitWeights);
This class implements the abstract base class for all AnyCamera objects.
Definition: AnyCamera.h:130
virtual VectorT2< T > projectToImageIF(const VectorT3< T > &objectPoint) const =0
Projects a 3D object point into the camera frame.
virtual bool isValid() const =0
Returns whether this camera is valid.
static HomogenousMatrixT4< U > standard2InvertedFlipped(const HomogenousMatrixT4< U > &world_T_camera)
Transforms a standard homogenous 4x4 viewing (extrinsic camera) matrix into an inverted and flipped c...
Definition: Camera.h:734
static bool isObjectPointInFrontIF(const HomogenousMatrixT4< T > &flippedCamera_T_world, const VectorT3< T > &objectPoint, const T epsilon=NumericT< T >::eps())
Determines whether a given 3D object point lies in front of a camera while the location of the camera...
Definition: Camera.h:811
This class implements an element storing the error between to image points.
Definition: Error.h:59
ErrorElement(const unsigned int imageIndex, const unsigned int candidateIndex, const Scalar error)
Creates a new error element.
Definition: Error.h:627
unsigned int imageIndex() const
Returns the index of the image point.
Definition: Error.h:635
Scalar error_
Error between the two points.
Definition: Error.h:104
unsigned int candidateIndex() const
Return the index of the candidate point.
Definition: Error.h:640
bool operator<(const ErrorElement &element) const
Returns whether the left element has a smaller error than the right one.
Definition: Error.h:650
Scalar error() const
Returns the error between the two points.
Definition: Error.h:645
This class implements to functions to determine the error or accuracy of geometric functions and thei...
Definition: Error.h:34
static Scalar determineHomographyError(const SquareMatrix3 &points1_H_points0, const TAccessorImagePoints &imagePointAccessor0, const TAccessorImagePoints &imagePointAccessor1, Vector2 *errors=nullptr, Scalar *sqrErrors=nullptr)
Determines the accuracy of a given homography for a set of corresponding image points.
Definition: Error.h:676
static Vector2 determinePoseError(const HomogenousMatrix4 &world_T_camera, const AnyCamera &camera, const Vector3 &objectPoint, const Vector2 &imagePoint)
Determines the accuracy of the camera pose based on 2D/3D correspondences.
Definition: Error.h:767
static Scalar uniqueAveragedRobustErrorInPointCloud(const Vector2 *imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Vector2 *candidatePoints, const size_t numberCandidatePoints, IndexPairs32 *correspondences=nullptr)
Determines the unique robust minimal average square error between two 2D points clouds.
Definition: Error.h:1087
static Scalar determineAverageError(const SquareMatrix3 &firstTransformation, const Vectors2 &firstPoints, const SquareMatrix3 &secondTransformation, const Vectors2 &secondPoints)
Returns the average square error between two sets of 2D positions.
static void determineCameraError(const PinholeCamera &pinholeCamera, const Vector2 *normalizedObjectPoints, const Vector2 *imagePoints, const size_t correspondences, const bool useDistortionParameters, Scalar &sqrAveragePixelError, Scalar &sqrMinimalPixelError, Scalar &sqrMaximalPixelError)
Determines the accuracy of the intrinsic camera matrix (and camera distortion parameters if requested...
static Scalar determineAverageError(const Vectors3 &firstPoints, const Vectors3 &secondPoints)
Returns the average square error between two sets of 3D positions.
static Scalar determineCameraError(const PinholeCamera &pinholeCamera, const Vector2 *normalizedObjectPoints, const Vector2 *imagePoints, const size_t correspondences, const bool useDistortionParameters, Vector2 *errors=nullptr, Scalar *sqrErrors=nullptr)
Determines the accuracy of the intrinsic camera matrix (and camera distortion parameters if requested...
static void determineInvalidParameters(const Scalar *parameters, const size_t number, const Scalar threshold, Indices32 &validIndices)
Determines the indices of a set of given parameter values that are above a provided threshold.
static Scalar determineError(const Vectors2 &firstPoints, const Vectors2 &secondPoints, Scalar &sqrAverageError, Scalar &sqrMinimalError, Scalar &sqrMaximalError)
Determining the average, minimal and maximal square error between two sets of 2D positions.
static Scalar averagedRobustError(const Scalar *sqrErrors, const size_t number, const Scalar *explicitWeights=nullptr)
Returns the averaged robust error for a given set of error values using a defined estimator.
Definition: Error.h:1388
static Scalar approximatedAveragedRobustErrorInPointCloud(const Vector2 *imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Vector2 *candidatePoints, const size_t numberCandidatePoints, IndexPairs32 *correspondences=nullptr)
Determines the approximated robust minimal average square error between two 2D points clouds.
Definition: Error.h:1186
static bool posesAlmostEqual(const HomogenousMatrix4 &poseFirst, const HomogenousMatrix4 &poseSecond, const Vector3 &maxTranslationOffset=Vector3(Scalar(0.1), Scalar(0.1), Scalar(0.1)), const Scalar maxOrientationOffset=Numeric::deg2rad(15))
Returns whether the offsets between two given 6DOF poses are below specified thresholds.
std::vector< ErrorElement > ErrorElements
Definition of a vector holding error elements.
Definition: Error.h:110
static Scalar determineError(const Vectors3 &firstPoints, const Vectors3 &secondPoints, Scalar &sqrAverageError, Scalar &sqrMinimalError, Scalar &sqrMaximalError)
Returns the average, minimal and maximal square error between two sets of 3D positions.
ErrorDetermination
Definition of different error determination stages.
Definition: Error.h:41
@ ED_APPROXIMATED
Approximated error determination.
Definition: Error.h:47
@ ED_INVALID
Invalid stage.
Definition: Error.h:43
@ ED_AMBIGUOUS
Ambiguous error determination.
Definition: Error.h:49
@ ED_UNIQUE
Unique error determination.
Definition: Error.h:45
static Scalar determineAverageError(const Vectors2 &firstPoints, const Vectors2 &secondPoints, Vector2 *errors=nullptr, Scalar *sqrErrors=nullptr)
Returns the average square error between two sets of 2D positions.
static Scalar averagedRobustErrorInPointCloud(const Vector2 *imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Vector2 *candidatePoints, const size_t numberCandidatePoints, const ErrorDetermination errorDetermination, IndexPairs32 *correspondences=nullptr)
Determines the unique robust minimal average square error between two 2D points clouds.
Definition: Error.h:1061
static Scalar ambiguousAveragedRobustErrorInPointCloud(const Vector2 *imagePoints, const size_t numberImagePoints, const size_t validImagePoints, const Vector2 *candidatePoints, const size_t numberCandidatePoints, IndexPairs32 *correspondences=nullptr)
Determines the ambiguous robust minimal average square error between two 2D points clouds.
Definition: Error.h:1287
static void determineValidParameters(const Scalar *parameters, const size_t number, const Scalar threshold, Indices32 &validIndices)
Determines the indices of a set of given parameter values that are below ore equal to a provided thre...
static Vector2 determinePoseErrorIF(const HomogenousMatrix4 &flippedCamera_T_world, const AnyCamera &camera, const Vector3 &objectPoint, const Vector2 &imagePoint)
Determines the accuracy of the camera pose based on 2D/3D correspondences.
Definition: Error.h:772
EstimatorType
Definition of individual robust estimator types.
Definition: Estimator.h:34
@ ET_HUBER
The Huber estimator type.
Definition: Estimator.h:84
@ ET_TUKEY
The Tukey estimator.
Definition: Estimator.h:102
@ ET_SQUARE
The standard square error estimator (L2).
Definition: Estimator.h:52
@ ET_LINEAR
The linear estimator (L1).
Definition: Estimator.h:66
@ ET_CAUCHY
The Cauchy estimator.
Definition: Estimator.h:118
VectorT3< T > translation() const
Returns the translation of the transformation.
Definition: HomogenousMatrix4.h:1381
bool isValid() const
Returns whether this matrix is a valid homogeneous transformation.
Definition: HomogenousMatrix4.h:1806
QuaternionT< T > rotation() const
Returns the rotation of the transformation as quaternion.
Definition: HomogenousMatrix4.h:1388
static constexpr T deg2rad(const T deg)
Converts deg to rad.
Definition: Numeric.h:3232
static T abs(const T value)
Returns the absolute value of a given value.
Definition: Numeric.h:1220
static constexpr T eps()
Returns a small epsilon.
static constexpr T sqr(const T value)
Returns the square of a given value.
Definition: Numeric.h:1495
static T cos(const T value)
Returns the cosine of a given value.
Definition: Numeric.h:1584
static constexpr bool isNotEqualEps(const T value)
Returns whether a value is not smaller than or equal to a small epsilon.
Definition: Numeric.h:2237
static constexpr T maxValue()
Returns the max scalar value.
Definition: Numeric.h:3244
bool hasDistortionParameters() const
Returns whether this camera object has specified distortion parameters.
Definition: PinholeCamera.h:1293
const SquareMatrixT3< T > & intrinsic() const
Returns the intrinsic camera matrix.
Definition: PinholeCamera.h:1257
HomogenousMatrixT4< T > transformationMatrixIF(const HomogenousMatrixT4< T > &iFlippedExtrinsic, const T zoom=T(1)) const
Returns a 4x4 homogenous transformation matrix (corresponding to a 3x4 matrix) that covers an extrins...
Definition: PinholeCamera.h:1479
VectorT2< T > projectToImageIF(const HomogenousMatrixT4< T > &flippedCamera_T_world, const VectorT3< T > &objectPoint, const bool distortImagePoint, const T zoom=T(1)) const
Projects a 3D object point to the 2D image plane of the camera by a given inverse camera pose.
Definition: PinholeCamera.h:1816
T cos2(const QuaternionT< T > &quaternion) const
Returns the cosine value of the half angle between two quaternion rotations.
Definition: Quaternion.h:857
bool multiply(const VectorT2< T > &vector, VectorT2< T > &result) const
Multiplies a 2D vector with this matrix (from the right).
Definition: SquareMatrix3.h:1708
bool isSingular() const
Returns whether this matrix is singular (and thus cannot be inverted).
Definition: SquareMatrix3.h:1341
T sqr() const
Returns the square of the vector length.
Definition: Vector2.h:621
T sqrDistance(const VectorT2< T > &right) const
Returns the square distance between this 2D position and a second 2D position.
Definition: Vector2.h:633
const T & y() const noexcept
Returns the y value.
Definition: Vector3.h:812
const T & x() const noexcept
Returns the x value.
Definition: Vector3.h:800
const T & z() const noexcept
Returns the z value.
Definition: Vector3.h:824
std::vector< IndexPair32 > IndexPairs32
Definition of a vector holding 32 bit index pairs.
Definition: Base.h:144
std::vector< Index32 > Indices32
Definition of a vector holding 32 bit index values.
Definition: Base.h:96
std::pair< Index32, Index32 > IndexPair32
Definition of a pair holding 32 bit indices.
Definition: Base.h:138
float Scalar
Definition of a scalar type.
Definition: Math.h:128
std::vector< Scalar > Scalars
Definition of a vector holding Scalar objects.
Definition: Math.h:144
VectorT3< Scalar > Vector3
Definition of a 3D vector.
Definition: Vector3.h:22
std::vector< Vector2 > Vectors2
Definition of a vector holding Vector2 objects.
Definition: Vector2.h:64
std::vector< Vector3 > Vectors3
Definition of a vector holding Vector3 objects.
Definition: Vector3.h:65
VectorT2< Scalar > Vector2
Definition of a 2D vector.
Definition: Vector2.h:21
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15