上一节《关于OpenCV的那些事——跟踪点选取方式和特征点跟踪恢复》讲了两种跟踪和恢复的方法,这一篇主要讲第一个优化,使用random sample consensus收敛相机姿态。下一篇讲使用最小二乘多项式平滑消除姿态抖动。
我们知道在计算相机姿态的时候,opencv中提供了两种函数:solvePnP, solvePnPRansac。 第二个函数即是利用ransac的思想计算更加精确的姿态。 鉴于之前章节《关于OpenCV的那些事——相机姿态更新》里讲到的相机姿态更新至少使用4组2D/3D点对,我们自己试着实现一下RANSAC。 思想是对于追踪的n个特征点对,我们先随机生成m个4组点对(m < Cn4(排列组合)),分别计算出m个姿态,然后对于每一个姿态计算重投影误差,小于一定阀值的记录下来,并更新最佳姿态(最小误差),最终返回这个最佳姿态。m也叫迭代次数。当然选择合适的m,既能节省时间,有能找到最佳姿态。重投影误差的阀值也需要做实验找到最合适的。
C++代码如下:
bool collinear_ornot(Point2f p1, Point2f p2, Point2f p3) // 三点是否共线
{
if (abs((p2.x - p1.x)*p3.y - (p2.y - p1.y)*p3.x - p1.y*p2.x + p1.x*p2.y) < 1e-5)
return true;
else
return false;
}
void random_n_4p(vector<Point2f>& imgP)
{
srand((unsigned)time(NULL));
int n = imgP.size(); //n为追踪的特征点的个数
for (int i = 0; i < ransac_1; i++) // ransac_1为上文中的m迭代次数,本项目中取20
{
do
{
n_4[i][0] = rand() % n;
do
{