OpenCV最小二乘法拟合空间平面

输入一个三维点的数组 std::vectorcv::Point3f Points3ds;
找到一个平面
Z=Ax+By+C
根据最小二乘法,使各个点到这个平面的距离最近:
S=∑(Axi + Byi + C – Zi) 2
求使得S最小的ABC的数值
首先取得最小值时,对各参数偏导数为零。
{ ∂ S ∂ A = 0 ∂ S ∂ B = 0 ∂ S ∂ C = 0 \left{\begin{array}{l}\frac{\partial S}{\partial A}=0 \ \ \frac{\partial S}{\partial B}=0 \ \\frac{\partial S}{\partial C}=0\end{array}\right.⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧​∂A ∂S ​=0 ∂B ∂S ​=0 ∂C ∂S ​=0 ​

求偏导:

{ A ∑ x i 2 + B ∑ y i x i + C ∑ x i = ∑ z i x i A ∑ x i y i + B ∑ y i 2 + C ∑ y i = ∑ z i y i A ∑ x i + B ∑ y i + C n = ∑ z i \left{\begin{array}{l}A \sum x_{i}^{2}+B \sum y_{i} x_{i}+C \sum x_{i}=\sum z_{i} x_{i} \ \ A \sum x_{i} y_{i}+B \sum y_{i}{ }^{2}+C \sum y_{i}=\sum z_{i} y_{i} \ \ A \sum x_{i}+B \sum y_{i}+C n=\sum z_{i}\end{array}\right.⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧​A ∑x i 2 ​+B ∑y i ​x i ​+C ∑x i ​=∑z i ​x i ​A ∑x i ​y i ​+B ∑y i ​2 +C ∑y i ​=∑z i ​y i ​A ∑x i ​+B ∑y i ​+C n =∑z i ​​
整理得

{ ∑ 2 ( A x i + B y i + C − z i ) x i = 0 ∑ 2 ( A x i + B y i + C − z i ) y i = 0 ∑ 2 ( A x i + B y i + C − z i ) = 0 \left{\begin{array}{l}\sum 2\left(A x_{i}+B y_{i}+C-z_{i}\right) x_{i}=0 \ \ \sum 2\left(A x_{i}+B y_{i}+C-z_{i}\right) y_{i}=0 \\ \sum 2\left(A x_{i}+B y_{i}+C-z_{i}\right)=0\end{array}\right.⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧​∑2 (A x i ​+B y i ​+C −z i ​)x i ​=0 ∑2 (A x i ​+B y i ​+C −z i ​)y i ​=0 ∑2 (A x i ​+B y i ​+C −z i ​)=0 ​
写为矩阵方程

∣ ∑ x i 2 ∑ x i y i ∑ x i ∑ x i y i ∑ y i 2 ∑ y i ∑ x i ∑ y i n ∣ ⋅ ∣ A B C ∣ = ∣ ∑ z i x i ∑ z i y i ∑ z i ∣ \left|\begin{array}{ccc}\sum x_{i}^{2} & \sum x_{i} y_{i} & \sum x_{i} \\ \sum x_{i} y_{i} & \sum y_{i}^{2} & \sum y_{i} \\ \sum x_{i} & \sum y_{i} & n\end{array}\right| \cdot\left|\begin{array}{l} A \\ B \\C \end{array}\right|=\left|\begin{array}{c}\sum z_{i} x_{i} \ \\sum z_{i} y_{i} \\ \sum z_{i}\end{array}\right|∣∣∣∣∣∣∣∣∣∣​∑x i 2 ​∑x i ​y i ​∑x i ​​∑x i ​y i ​∑y i 2 ​∑y i ​​∑x i ​∑y i ​n ​∣∣∣∣∣∣∣∣∣∣​⋅∣∣∣∣∣∣∣∣∣∣​A B C ​∣∣∣∣∣∣∣∣∣∣​=∣∣∣∣∣∣∣∣∣∣​∑z i ​x i ​∑z i ​y i ​∑z i ​​∣∣∣∣∣∣∣∣∣∣​
矩阵方程 A ⋅ \cdot ⋅x=b
A是参数矩阵,不是上面多项式的参数,b是向量
通解 x=A-1 ⋅ \cdot ⋅b
得到参数向量
∣ A B C ∣ \left|\begin{array}{l} A \ B \C \end{array}\right|∣∣∣∣∣∣​A B C ​∣∣∣∣∣∣​
代码如下:

void CaculateLaserPlane(std::vector<cv::Point3f> Points3ds,vector<double> &res)
{

    cv::Mat A = cv::Mat::zeros(3, 3, CV_64FC1);

    cv::Mat B = cv::Mat::zeros(3, 1, CV_64FC1);

    cv::Mat X = cv::Mat::zeros(3, 1, CV_64FC1);
    double x2 = 0, xiyi = 0, xi = 0, yi = 0, zixi = 0, ziyi = 0, zi = 0, y2 = 0;
    for (int i = 0; i < Points3ds.size(); i++)
    {
        x2 += (double)Points3ds[i].x * (double)Points3ds[i].x;
        y2 += (double)Points3ds[i].y * (double)Points3ds[i].y;
        xiyi += (double)Points3ds[i].x * (double)Points3ds[i].y;
        xi += (double)Points3ds[i].x;
        yi += (double)Points3ds[i].y;
        zixi += (double)Points3ds[i].z * (double)Points3ds[i].x;
        ziyi += (double)Points3ds[i].z * (double)Points3ds[i].y;
        zi += (double)Points3ds[i].z;
    }
    A.at<double>(0, 0) = x2;
    A.at<double>(1, 0) = xiyi;
    A.at<double>(2, 0) = xi;
    A.at<double>(0, 1) = xiyi;
    A.at<double>(1, 1) = y2;
    A.at<double>(2, 1) = yi;
    A.at<double>(0, 2) = xi;
    A.at<double>(1, 2) = yi;
    A.at<double>(2, 2) = Points3ds.size();
    B.at<double>(0, 0) = zixi;
    B.at<double>(1, 0) = ziyi;
    B.at<double>(2, 0) = zi;

    X = A.inv() * B;

    res.push_back(X.at<double>(0, 0));

    res.push_back(X.at<double>(1, 0));

    res.push_back(1.0);

    res.push_back(X.at<double>(2, 0));
    return;
}

Original: https://blog.csdn.net/u011725598/article/details/123739539
Author: Jieckiee
Title: OpenCV最小二乘法拟合空间平面

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/701929/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球