非线性优化Ceres拟合圆

1.问题描述

已知圆方程
r 2 = ( x − x 0 ) 2 + ( y − y 0 ) 2 r^2=(x-x_0)^2+(y-y_0)^2 r2=(xx0)2+(yy0)2
其中x0,y0,r为曲线待拟合参数。
假设我们有N个关于x,y的观测数据点,想根据这些数据点求出曲线的参数。那么可以求解下面的最小二乘问题。
为了拟合圆方程,直接用y为x的函数
min ⁡ a , b 1 2 ∑ i = 1 N ∥ y i − f ( x i ) ) ) ∥ 2 \min_{a,b}\frac{1}{2}\sum_{i=1}^{N}\left \| y_{i}-f(x_i))) \right \|^{2} a,bmin21i=1Nyif(xi)))2
会牵涉到正负号的问题。
定义残差函数如下(这个如何表示欢迎指正
min ⁡ a , b 1 2 ∑ i = 1 N ∥ r 2 − ( x − x 0 ) 2 + ( y − y 0 ) 2 ) ) ∥ 2 \min_{a,b}\frac{1}{2}\sum_{i=1}^{N}\left \|r^2-(x-x_0)^2+(y-y_0)^2)) \right \|^{2} a,bmin21i=1Nr2(xx0)2+(yy0)2))2
实现代码如下
代码

#include <iostream>
#include <opencv2/core/core.hpp>
#include <ceres/ceres.h>
#include <chrono>

using namespace std;


struct CICLE_FITTING_COST
{
    CICLE_FITTING_COST ( double x, double y ) : _x ( x ), _y ( y ) {}
    // 残差的计算
    template <typename T>
    bool operator() (
        const T* const x0y0r,     // 模型参数,有3维
        T* residual ) const     // 残差
    {
        //(x-x0)^2+(y-y0)^2-r^2
        residual[0]=x0y0r[2]-(T ( _x )-x0y0r[0])*(T ( _x )-x0y0r[0])-(T ( _y )-x0y0r[1])*(T ( _y )-x0y0r[1]);
        return true;
    }
    const double _x, _y;    // x,y数据
};




int main ( int argc, char** argv )
{
    double x0=-3.0, y0=-4.0, r=2.0;         // 真实参数值
    int N=100;                          // 数据点
    double w_sigma=0.001;                 // 噪声Sigma值
    cv::RNG rng;                        // OpenCV随机数产生器
    double x0y0r[3] = {0,0,0};            // abc参数的估计值

    vector<double> x_data, y_data;      // 数据

    cout<<"generating data: "<<endl;

    for ( int i=0; i<N; i++ )
    {
        double x = x0+r*cos(i*M_PI/50);
        double noise_y=y0+r*sin(i*M_PI/50)+rng.gaussian ( w_sigma );
        x_data.push_back ( x );
        y_data.push_back (noise_y);
        cout<<x_data[i]<<" "<<y_data[i]<<endl;
    }
    ceres::Problem problem;
    for ( int i=0; i<N; i++ )
    {
        problem.AddResidualBlock (     // 向问题中添加误差项
        // 使用自动求导,模板参数:误差类型,输出维度,输入维度,维数要与前面struct中一致
            new ceres::AutoDiffCostFunction<CICLE_FITTING_COST, 1, 3> (
                new CICLE_FITTING_COST ( x_data[i], y_data[i] )
            ),
            nullptr,            // 核函数,这里不使用,为空
            x0y0r                 // 待估计参数
        );
    }
    // 配置求解器
    ceres::Solver::Options options;     // 这里有很多配置项可以填
    options.linear_solver_type = ceres::DENSE_QR;  // 增量方程如何求解
    options.minimizer_progress_to_stdout = true;   // 输出到cout

    ceres::Solver::Summary summary;                // 优化信息
    chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
    ceres::Solve ( options, &problem, &summary );  // 开始优化
    chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
    chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>(t2-t1 );
    cout<<"solve time cost = "<<time_used.count()<<" seconds. "<<endl;
    // 输出结果
    cout<<summary.BriefReport() <<endl;
//    cout<<"estimated x0,y0,r = ";
    cout<<"x0 "<<x0y0r[0]<<"y0= "<<x0y0r[1]<<" r= "<<sqrt(x0y0r[2]);
    return 0;
}

曲线拟合相关系数参考
https://www.engr.uidaho.edu/thompson/courses/ME330/lecture/least_squares.html

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值