Fix #145185: Crash while solving camera motion
The crash happens in specific cases when doing euclidean resection in cases when first 3 3D estimates are correlated. While it is a bit cryptic on user level, what it could mean is: - Either there are overlapping markers - Or the optical system is highly out of calibration. Either of these cases is not the primary goal to support with camera solvers in Libmv for the time being, so while this change avoids the crash there is possibility to make algorithm more robustly handle the tracking data and potentially give better result. Such correlation via some intermediate steps leads to the algorithm attempting to perform SVD decomposition of a matrix with NaN values in it. The exact reason of the crash is not super clear as it happens deep in the JacobiSVD decomposition code in Eigen and caused by invalid index somewhere. It might be a bug in Eigen which doesn't do range checking, hoping that the math does not fail in cases like NaN and inf. Pull Request: https://projects.blender.org/blender/blender/pulls/145301
This commit is contained in:
committed by
Sergey Sharybin
parent
20a19c7aa4
commit
1d88e19c32
@@ -377,7 +377,7 @@ static void SelectControlPoints(const Mat3X& X_world,
|
||||
}
|
||||
|
||||
// Computes the barycentric coordinates for all real points
|
||||
static void ComputeBarycentricCoordinates(const Mat3X& X_world_centered,
|
||||
static bool ComputeBarycentricCoordinates(const Mat3X& X_world_centered,
|
||||
const Mat34& X_control_points,
|
||||
Mat4X* alphas) {
|
||||
size_t num_points = X_world_centered.cols();
|
||||
@@ -386,7 +386,21 @@ static void ComputeBarycentricCoordinates(const Mat3X& X_world_centered,
|
||||
C2.col(c - 1) = X_control_points.col(c) - X_control_points.col(0);
|
||||
}
|
||||
|
||||
Mat3 C2inv = C2.inverse();
|
||||
// The selected basis might have correlated vectors causing inverse to produce
|
||||
// undefined result which could lead to issues later on in SVD decomposition.
|
||||
//
|
||||
// Evidently, when built with MSVC it could lead to crash in SVD when the
|
||||
// input contains NaN values:
|
||||
// https://projects.blender.org/blender/blender/issues/145185
|
||||
//
|
||||
// TODO(sergey): Look into choosing a different basis in these cases.
|
||||
bool is_invertible;
|
||||
Mat3 C2inv;
|
||||
C2.computeInverseWithCheck(C2inv, is_invertible);
|
||||
if (!is_invertible) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Mat3X a = C2inv * X_world_centered;
|
||||
|
||||
alphas->resize(4, num_points);
|
||||
@@ -395,6 +409,8 @@ static void ComputeBarycentricCoordinates(const Mat3X& X_world_centered,
|
||||
for (size_t c = 0; c < num_points; c++) {
|
||||
(*alphas)(0, c) = 1.0 - alphas->col(c).sum();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Estimates the coordinates of all real points in the camera coordinate frame
|
||||
@@ -450,7 +466,9 @@ bool EuclideanResectionEPnP(const Mat2X& x_camera,
|
||||
|
||||
// Compute the barycentric coordinates.
|
||||
Mat4X alphas(4, num_points);
|
||||
ComputeBarycentricCoordinates(X_centered, X_control_points, &alphas);
|
||||
if (!ComputeBarycentricCoordinates(X_centered, X_control_points, &alphas)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Estimates the M matrix with the barycentric coordinates
|
||||
Mat M(2 * num_points, 12);
|
||||
|
||||
Reference in New Issue
Block a user