C++opencv实现最小二乘法拟合直线和平面

本文介绍如何利用OpenCV的Mat类通过最小二乘法来拟合二维直线和三维平面方程。文中提供了具体的C++实现代码,并演示了如何通过一系列点集计算出最优的直线和平面参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用opencv中的Mat实现用矩阵的方式根据最小二乘法拟合直线和平面方程,但是好像不能实现拟合斜率无穷大的直线和平面方程,后续再改进吧。
有关于原理部分,有时间再详细写一下。

#include "stdafx.h"
#include <opencv2/opencv.hpp>  
#include <vector>  
#include <iostream>  
#include <fstream>  

#pragma warning(disable:4244)

using namespace cv;
using namespace std;

/*输入一组坐标值,根据最小二乘法计算直线方程 y = kx + b 
先返回斜率 k ,再返回截距 b*/
Mat OLS_Line(vector<Point> point)
{
    //Ax = b的形式,将A b 写成矩阵的形式
    Mat A((int)point.size(), 2, CV_32F);
    Mat b((int)point.size(), 1, CV_32F);

    //初始化矩阵A
    for (size_t i = 0; i<point.size(); i++)
        A.at<float>((int)i, 1) = 1;
    for (size_t i = 0; i< point.size(); i++)
        A.at<float>((int)i, 0) = point[i].x;
//  cout <<矩阵A:<< endl << A << endl;

    //初始化矩阵b 
    for (size_t i = 0; i< point.size(); i++)
        b.at<float>((int)i, 0) = point[i].y;
//  cout <<"矩阵b"<< endl << b << endl;

    //根据线性代数知识,A'* A * x = A' * b 求得的矩阵 x 即为最优解
    //解 x = (A' * A)^-1 * A' * b

    Mat x = (A.t()*A).inv()*A.t()*b;

    return x;
}


/*输入一组坐标值,根据最小二乘法计算平面方程
分别返回 a ,b, c 的值
aX + bY - Z + c = 0 */
Mat OLS_Plane(vector<Point3f> point)
{
    //Ax = 0的形式,将A, b 写成矩阵的形式
    Mat A((int)point.size(), 3, CV_32F);
    Mat b((int)point.size(), 1, CV_32F);

//  cout <<"原始点为:"<< point << endl;

    //初始化矩阵A
    for (size_t i = 0; i< point.size(); i++)
        A.at<float>((int)i, 0) = (point[i].x);

    for (size_t i = 0; i< point.size(); i++)
        A.at<float>((int)i, 1) = (point[i].y);

    for (size_t i = 0; i<point.size(); i++)
        A.at<float>((int)i, 2) = 1;

//  cout << "矩阵A:" << endl << A << endl;

    //初始化矩阵b 
    for (size_t i = 0; i< point.size(); i++)
        b.at<float>((int)i, 0) = -(point[i].z);

//  cout << "矩阵b:" << endl << b << endl;

    //根据线性代数知识,A'* A * x = A' * b 求得的矩阵 x 即为最优解
    //解 x = (A' * A)^-1 * A' * b

    Mat x = -((A.t()*A).inv()*A.t()*b);

    return x;
}


int main()
{
    vector<Point> point;
    point.push_back(Point(1, 1));
    point.push_back(Point(2, 2));
    point.push_back(Point(3, 2));
    //point.push_back(Point(4, 10));

    cout << OLS_Line(point) << endl;;

    vector<Point3f> point3;
    point3.push_back(Point3f(2, -1,4));
    point3.push_back(Point3f(-1, 3, -2));
    point3.push_back(Point3f(0, 2, 5));
    point3.push_back(Point3f(0, 0, -14));
    //cout << point3 << endl;
    cout << OLS_Plane(point3) << endl;


    vector<Point3f> point33;
    point33.push_back(Point3f(-1, -1, -5));
    point33.push_back(Point3f(-8, 1, 0));
    point33.push_back(Point3f(3, 2, -12));
    point33.push_back(Point3f(0, 0, -8));
    //cout << point33 << endl;
    cout << OLS_Plane(point33) << endl;

    waitKey(0);
    system("pause");
    return 0;
}
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值