我有两组3D点(原始的和重构的)和关于对的对应信息--从一组中的点代表第二组。我需要找到3D平移和缩放因子来转换重建集,使平方距离之和最小(旋转也很好,但是点也是同样旋转的,所以这不是主要的优先级,为了简单和速度,这可能被省略)。所以我的问题是--这个问题在互联网上得到解决了吗?就我个人而言,我会使用最小二乘法,但我没有太多的时间(虽然我有点擅长数学,但我不经常使用它,所以最好避免它),所以如果它存在的话,我想使用别人的解决方案。我更喜欢C++中的解决方案,例如使用OpenCV,但是算法本身就足够好了。
如果没有这样的解决方案,我会自己计算,我不想打扰你这么多。
解决方案:(来自您的答案)
对我来说,这是一种卡布希算法;
基本信息:算法
通用解决方案:id=671
还没有解决:我也需要规模。SVD的标度值对我来说是不可理解的;当我需要所有轴的1-4标度时(据我估计),SVD的标度约为2000,200,20,这一点也没有帮助。
发布于 2015-08-27 08:53:53
既然您已经在使用Kabsch,那么只需看一看Umeyama论文,它就可以扩展它以获得扩展。你所需要做的就是得到你的点的标准差,并计算标度如下:
(1/sigma^2)*trace(D*S)其中,D是旋转估计中奇异值分解中的对角矩阵,S是单位矩阵或[1 1 -1]对角矩阵,这取决于UV行列式的符号(UV用于校正反射到适当的旋转)。所以如果你有[2000, 200, 20],把最后一个元素乘以+-1 (取决于UV行列式的符号),把它们加起来,除以点的标准差,得到标度。
可以循环使用本征库的下列代码:
typedef Eigen::Matrix<double, 3, 1, Eigen::DontAlign> Vector3d_U; // microsoft's 32-bit compiler can't put Eigen::Vector3d inside a std::vector. for other compilers or for 64-bit, feel free to replace this by Eigen::Vector3d
/**
* @brief rigidly aligns two sets of poses
*
* This calculates such a relative pose <tt>R, t</tt>, such that:
*
* @code
* _TyVector v_pose = R * r_vertices[i] + t;
* double f_error = (r_tar_vertices[i] - v_pose).squaredNorm();
* @endcode
*
* The sum of squared errors in <tt>f_error</tt> for each <tt>i</tt> is minimized.
*
* @param[in] r_vertices is a set of vertices to be aligned
* @param[in] r_tar_vertices is a set of vertices to align to
*
* @return Returns a relative pose that rigidly aligns the two given sets of poses.
*
* @note This requires the two sets of poses to have the corresponding vertices stored under the same index.
*/
static std::pair<Eigen::Matrix3d, Eigen::Vector3d> t_Align_Points(
const std::vector<Vector3d_U> &r_vertices, const std::vector<Vector3d_U> &r_tar_vertices)
{
_ASSERTE(r_tar_vertices.size() == r_vertices.size());
const size_t n = r_vertices.size();
Eigen::Vector3d v_center_tar3 = Eigen::Vector3d::Zero(), v_center3 = Eigen::Vector3d::Zero();
for(size_t i = 0; i < n; ++ i) {
v_center_tar3 += r_tar_vertices[i];
v_center3 += r_vertices[i];
}
v_center_tar3 /= double(n);
v_center3 /= double(n);
// calculate centers of positions, potentially extend to 3D
double f_sd2_tar = 0, f_sd2 = 0; // only one of those is really needed
Eigen::Matrix3d t_cov = Eigen::Matrix3d::Zero();
for(size_t i = 0; i < n; ++ i) {
Eigen::Vector3d v_vert_i_tar = r_tar_vertices[i] - v_center_tar3;
Eigen::Vector3d v_vert_i = r_vertices[i] - v_center3;
// get both vertices
f_sd2 += v_vert_i.squaredNorm();
f_sd2_tar += v_vert_i_tar.squaredNorm();
// accumulate squared standard deviation (only one of those is really needed)
t_cov.noalias() += v_vert_i * v_vert_i_tar.transpose();
// accumulate covariance
}
// calculate the covariance matrix
Eigen::JacobiSVD<Eigen::Matrix3d> svd(t_cov, Eigen::ComputeFullU | Eigen::ComputeFullV);
// calculate the SVD
Eigen::Matrix3d R = svd.matrixV() * svd.matrixU().transpose();
// compute the rotation
double f_det = R.determinant();
Eigen::Vector3d e(1, 1, (f_det < 0)? -1 : 1);
// calculate determinant of V*U^T to disambiguate rotation sign
if(f_det < 0)
R.noalias() = svd.matrixV() * e.asDiagonal() * svd.matrixU().transpose();
// recompute the rotation part if the determinant was negative
R = Eigen::Quaterniond(R).normalized().toRotationMatrix();
// renormalize the rotation (not needed but gives slightly more orthogonal transformations)
double f_scale = svd.singularValues().dot(e) / f_sd2_tar;
double f_inv_scale = svd.singularValues().dot(e) / f_sd2; // only one of those is needed
// calculate the scale
R *= f_inv_scale;
// apply scale
Eigen::Vector3d t = v_center_tar3 - (R * v_center3); // R needs to contain scale here, otherwise the translation is wrong
// want to align center with ground truth
return std::make_pair(R, t); // or put it in a single 4x4 matrix if you like
}发布于 2014-08-09 23:02:46
对于三维点,这个问题被称为绝对方向问题。c++实现可以从特征Module.html#gab3f5a82a24490b936f8694cf8fef8e60和纸张http://web.stanford.edu/class/cs273/refs/umeyama.pdf中获得。
您可以通过opencv使用cv::cv2eigen()调用将矩阵转换为特征。
发布于 2012-11-18 04:37:35
一个很好的解释寻找最佳旋转和对应三维点之间的平移
代码在matlab中,但是使用cv::SVD函数将代码转换为opengl非常简单
https://stackoverflow.com/questions/13432805
复制相似问题