I have a problem that involves finding translations for a 3D point cloud that will take each point to a location that minimizes a certain error.
As I am new to Ceres and automatic differentiation methods, I built a very simplified version of the problem in order to learn how to use residual blocks properly when solving for several points. Also, the original problem requires using a 3rd party function, so I used the CostFunctionToFunctor interface for the simplified version, despite it not being necessary.
The simplified problem is as follows:
I have a 3D point cloud, and I want to find the translation [x y z] that will bring each point to the origin (0, 0, 0).
In my main AutoDiff Cost Function, I pass the x, y and z components of a point as doubles and set "translation" as the parameter to minimize. Inside the evaluator, I add the translation to the point as such:
T pointPlusTranslation[3];
pointPlusTranslation[0] = T( point_x ) + translation[0];
pointPlusTranslation[1] = T( point_y ) + translation[1];
pointPlusTranslation[2] = T( point_z ) + translation[2];
I then pass this newly translated point to a new function that evaluates the distance between the newly translated point and the origin, using this value as the error to minimize.
In the main method, I iterate through all points in my point cloud and create a new cost function for each, adding it as a residual block to the ceres problem.
Now, this works perfectly if I split the residual per dimension as follows:
error[0] = (0. - *point_x);
error[1] = (0. - *point_y);
error[2] = (0. - *point_z);
In 2 iterations it reaches the ideal translation for each point.
However, if I instead pose a single scalar value as the error as such:
error[0] = (0. - *point_x) + (0. - *point_y) + (0. - *point_z);
it also converges after 2 iterations with a very small final error, but the values are incorrect.
For example, if one point is at (0.0514317, 1.40441, -11.2916), the ideal translation should be (-0.0514317, -1.40441, 11.2916).
Instead, with this error the program yields (3.57952, 2.94071, 3.3155).
In this problem, it is feasible to split the error per point dimension, but in the more complex version, the error criteria does not allow this (it’s the variance of the pixel intensity obtained by projecting the point onto several images). Regardless of the feasibility of splitting the residual like this for each problem, I simply can’t understand why it wouldn’t work to have one scalar error. I think I am missing some fundamental understanding of Ceres with an error dependent on multiple variables.
I attached a file with more detailed pseudocode for this simplified problem.
Thank you for your time!
Ceres minimizes the sum of squared errors of your residual. These aren't minimizing the same costs.
--
You received this message because you are subscribed to the Google Groups "Ceres Solver" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ceres-solver...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ceres-solver/69e97289-2daa-4926-a7e1-c6dcb2061b27%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
To view this discussion on the web visit https://groups.google.com/d/msgid/ceres-solver/5da67a81-109f-4aaf-8ccb-fca257a01334%40googlegroups.com.
Dear Sameer,Thank you so much for your response. It was very helpful to realize I was focusing too much on the math and not enough on what I was feeding the solver, and I now see why three residuals works better than one for the case I described - the more residuals, the more informative their Jacobian matrix will be. In fact, I realized that if the number of equations/residual functions is less than the amount of parameters we're solving for, the system is underdetermined and the Gauss-Newton iterations won't work, no?
So, for problems like this one where I can easily come up with three residuals, this is fine. However, what if I have only one error metric (and thus, one residual function) dependent on all 3 variables i'm minimizing with no way to separate them?
I'll explain myself:I have an AutoDiff functor that takes in a 3D point from a point cloud along with its associated normal, images and cameras. It minimizes a translation vector with 3 components that'll take the point to a new location that minimizes the variance in the pixel intensity when projected to each one of its images.So, the evaluating operator adds one translation component to its respective x,y,z component of the point, just like in the original problem I posted.The complication comes here, where I have a NumericDiff cost function that uses the CostFunctionToFunctor class to perform the error calculation:
- Project point to all images (we can assume it correctly projects within their bounds)
- For each image, save the intensity value of the pixel the point corresponds to
- Calculate the variance between all these intensity values, which is what we want to reduce
- Assign this variance directly to the error. This is where I think I'm wrong.
To view this discussion on the web visit https://groups.google.com/d/msgid/ceres-solver/04ce4e1b-5884-4858-9edd-b2fb755f3953%40googlegroups.com.
I think I found a way to phrase my doubt better: my error function (variance) isn't directly based on the minimization parameters (translations), it's based on pixel intensity, that is, scalars! This whole projection function that takes my 3D point + 3D translation is essentially a map from R3 to R1, and all differentiable information is lost, I think. I'm looking into the BiCubicInterpolator class to get a smooth approximation of my images. I hope I'm on the right track!
To view this discussion on the web visit https://groups.google.com/d/msgid/ceres-solver/b23bf3a9-5a60-420f-8851-5f13358d14a9%40googlegroups.com.