直线拟合的三种方法

article/2025/10/5 22:19:33

近日考虑直线拟合相关的知识,大概有所了解,所以打算进行一些总结。

直线拟合常用的三种方法:

一、最小二乘法进行直线拟合

二、梯度下降法进行直线拟合

三、高斯牛顿,列-马算法进行直线拟合

 

一、使用最多的就是最小二乘法,这里我也对最小二乘法进行了一个总结。

1. 假设x是正确值,y存在误差。

根据上面两图的手推公式我们可以编写相关的代码了。此处我们借助opencv工具进行结果显示和分析。

void fitline3(){float b = 0.0f, k=0.0f;vector<Point>points;points.push_back(Point(27, 39));points.push_back(Point(8, 5));points.push_back(Point(8, 9));points.push_back(Point(16, 22));points.push_back(Point(44, 71));points.push_back(Point(35, 44));points.push_back(Point(43, 57));points.push_back(Point(19, 24));points.push_back(Point(27, 39));points.push_back(Point(37, 52));Mat src = Mat::zeros(400, 400, CV_8UC3);for (int i = 0; i < points.size(); i++){//在原图上画出点circle(src, points[i], 3, Scalar(0, 255, 0), 1, 8);}int n = points.size();double xx_sum = 0;double x_sum = 0;double y_sum = 0;double xy_sum = 0;for (int i = 0; i < n; i++){x_sum += points[i].x; //x的累加和y_sum += points[i].y; //y的累加和xx_sum += points[i].x * points[i].x; //x的平方累加和xy_sum += points[i].x * points[i].y; //x,y的累加和}k = (n*xy_sum - x_sum * y_sum) / (n*xx_sum - x_sum * x_sum); //根据公式求解kb = (-x_sum * xy_sum + xx_sum*y_sum) / (n*xx_sum - x_sum * x_sum);//根据公式求解bprintf("k = %f, b = %f\n", k, b); //k = 1.555569, b = -4.867031cv::Point first = { 5, int(k * 5 + b) }, second = { int((400 - b) / k), 400 };cv::line(src, first, second, cv::Scalar(0, 0, 255), 2);cv::imshow("name", src);cv::waitKey(0);
}

上面求解出来的结果是k = 1.555569, b = -4.867031。

图像显示结果:

 

 

下面我们使用opencv自带的函数求解k和b值。此处代码来自互联网。

void fitline1()
{vector<Point>points;//(27 39) (8 5) (8 9) (16 22) (44 71) (35 44) (43 57) (19 24) (27 39) (37 52)points.push_back(Point(27, 39));points.push_back(Point(8, 5));points.push_back(Point(8, 9));points.push_back(Point(16, 22));points.push_back(Point(44, 71));points.push_back(Point(35, 44));points.push_back(Point(43, 57));points.push_back(Point(19, 24));points.push_back(Point(27, 39));points.push_back(Point(37, 52));Mat src = Mat::zeros(400, 400, CV_8UC3);for (int i = 0; i < points.size(); i++){//在原图上画出点circle(src, points[i], 3, Scalar(0, 0, 255), 1, 8);}//构建A矩阵 int N = 2;Mat A = Mat::zeros(N, N, CV_64FC1);for (int row = 0; row < A.rows; row++){for (int col = 0; col < A.cols; col++){for (int k = 0; k < points.size(); k++){A.at<double>(row, col) = A.at<double>(row, col) + pow(points[k].x, row + col);}}}//构建B矩阵Mat B = Mat::zeros(N, 1, CV_64FC1);for (int row = 0; row < B.rows; row++){for (int k = 0; k < points.size(); k++){B.at<double>(row, 0) = B.at<double>(row, 0) + pow(points[k].x, row)*points[k].y;}}//A*X=BMat X;//cout << A << endl << B << endl;solve(A, B, X, DECOMP_LU);cout << X << endl;vector<Point>lines;for (int x = 0; x < src.size().width; x++){				// y = b + ax;double y = X.at<double>(0, 0) + X.at<double>(1, 0)*x; //b = -4.867031, k = 1.555569,printf("b = %f, k = %f, (%d,%lf)\n", X.at<double>(0, 0), X.at<double>(1, 0), x, y);lines.push_back(Point(x, y));}polylines(src, lines, false, Scalar(255, 0, 0), 1, 8);imshow("src", src);//imshow("src", A);waitKey(0);
}

求解得出对应的k = 1.555569, b = -4.867031。

这两个结果值是一样的。说明我们的推导结果是正确的。

 

2. 上面的公式推导是假设了x是正确值,y存在误差,是普通的一元线性回归。

此处将离散的点拟合为 ax + by +c = 0型直线。

即假设每个点的x,y坐标的误差都是 符合0均值的正态分布的。

有如下代码:

void fitline2(){float a = 0.0f, b = 0.0f, c = 0.0f;vector<Point>points;points.push_back(Point(27, 39));points.push_back(Point(8, 5));points.push_back(Point(8, 9));points.push_back(Point(16, 22));points.push_back(Point(44, 71));points.push_back(Point(35, 44));points.push_back(Point(43, 57));points.push_back(Point(19, 24));points.push_back(Point(27, 39));points.push_back(Point(37, 52));Mat src = Mat::zeros(400, 400, CV_8UC3);for (int i = 0; i < points.size(); i++){//在原图上画出点circle(src, points[i], 3, Scalar(0, 255, 0), 1, 8);}int size = points.size();double x_mean = 0;double y_mean = 0;for (int i = 0; i < size; i++){x_mean += points[i].x;y_mean += points[i].y;}x_mean /= size;y_mean /= size; //至此,计算出了 x y 的均值double Dxx = 0, Dxy = 0, Dyy = 0;for (int i = 0; i < size; i++){Dxx += (points[i].x - x_mean) * (points[i].x - x_mean);Dxy += (points[i].x - x_mean) * (points[i].y - y_mean);Dyy += (points[i].y - y_mean) * (points[i].y - y_mean);}double lambda = ((Dxx + Dyy) - sqrt((Dxx - Dyy) * (Dxx - Dyy) + 4 * Dxy * Dxy)) / 2.0;double den = sqrt(Dxy * Dxy + (lambda - Dxx) * (lambda - Dxx));a = Dxy / den;b = (lambda - Dxx) / den;c = -a * x_mean - b * y_mean;printf("a = %f, b = %f, c = %f\n", a, b, c);printf("k = %f, b = %f\n", - a/b, -c/b); //k = 1.593043, b = -5.856340float k = -a / b;b = -c / b;cv::Point first = { 5, int(k * 5 + b) }, second = { int((400 - b) / k), 400 };cv::line(src, first, second, cv::Scalar(0, 0, 255), 2);cv::imshow("name", src);cv::waitKey(0);}

求解结果为k = 1.593043, b = -5.856340。(对比发现此方法和方法一结果还是存在差异的)

显示结果:

 

二、梯度下降法进行直线拟合

下图是我的手写推导公式:

推导公式中alpha为学习率,theta0和theta1分别是斜率k和截距b。m是为了求平均损失,2是为了求偏导方便。

根据推导公式写出如下代码:

//梯度下降法进行线性拟合
// y = theta0 * x + theta1
void fitline4(){const int m = 10;double Train_set_x[m] = { 27, 8, 8, 16, 44, 35, 43, 19, 27, 37 };double Train_set_y[m] = { 39, 5, 9, 22, 71, 44, 57, 24, 39, 52 };double theta0 = 0.0, theta1 = 0.0, alpha = 0.002, error = 1e-8; //alpha是学习率,error是结束误差,theta0就是k,theta1就是b。double tmp_theta0 = theta0, tmp_theta1 = theta1;double sum_theta0 = 0.0, sum_theta1 = 0.0;while (1){sum_theta0 = 0.0, sum_theta1 = 0.0;for (size_t i = 0; i < m; i++) {sum_theta0 += (theta0 * Train_set_x[i] + theta1 - Train_set_y[i])*Train_set_x[i]; //累加和sum_theta1 += (theta0 * Train_set_x[i] + theta1 - Train_set_y[i]);  //累加和}theta0 = theta0 - alpha * (1.0 / m) * sum_theta0; //k更新公式theta1 = theta1 - alpha * (1.0 / m) * sum_theta1; //b更新公式printf("k=%lf, b=%lf\n", theta0, theta1);if (abs(theta0 - tmp_theta0) < error && abs(theta1 - tmp_theta1) < error){ //break;}tmp_theta0 = theta0;tmp_theta1 = theta1;}
}

求解结果为k=1.555569, b=-4.867004。与最小二乘法的结果极为相似。

 

 

三、高斯牛顿,列-马算法

 

 


http://chatgpt.dhexx.cn/article/7vcagiZx.shtml

相关文章

手把手教你整合最优雅SSM框架:SpringMVC + Spring + MyBatis

我们看招聘信息的时候&#xff0c;经常会看到这一点&#xff0c;需要具备SSH框架的技能&#xff1b;而且在大部分教学课堂中&#xff0c;也会把SSH作为最核心的教学内容。 但是&#xff0c;我们在实际应用中发现&#xff0c;SpringMVC可以完全替代Struts&#xff0c;配合注解的…

F-LOAM

欢迎访问我的博客首页。 F-LOAM 1. 传感器模型与特征提取1.1 传感器模型1.2 特征提取 2. 运动估计与畸变补偿2.1 匀速运动模型2.2 祛畸变 3. 位姿估计4. 地图创建与畸变补偿更新5. 附录5.1 位姿变换的传递性 6. 参考 1. 传感器模型与特征提取 1.1 传感器模型 机械式三维激光雷达…

MinIO入门-02 SpringBoot 整合MinIO并实现文件上传

SpringBoot 整合MinIO并实现文件上传 1、依赖 <!-- https://mvnrepository.com/artifact/io.minio/minio --> <dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.3.9</version> </depen…

Invalid bound statement (not found): com.lyf.eduservice.mapper.EduCourseMapper.getpublishInfo

目录 问题分析&#xff1a; 解决方案&#xff1a; 问题分析&#xff1a; dao层编译后只有class文件&#xff0c;没有mapper.xml&#xff0c;因为maven工程在默认情况下src/main/java目录下的所有资源文件是不发布到target目录下的 解决方案&#xff1a; 第一步、在项目的po…

ELF

目录 一&#xff0c;目标文件格式 二&#xff0c;ELF 1&#xff0c;分段 2&#xff0c;工具 3&#xff0c;查看目标文件内容 一&#xff0c;目标文件格式 编译链接 https://blog.csdn.net/nameofcsdn/article/details/116654835 目标文件和可执行文件的逻辑结构是类似的…

littlefs

1、littlefs主要用在微控制器和flash上&#xff0c;是一种嵌入式文件系统。主要有3个特点&#xff1a; 1)、掉电恢复 在写入时即使复位或者掉电也可以恢复到上一个正确的状态。 2)、擦写均衡 有效延长flash的使用寿命 3)、有限的RAM/ROM 节省ROM和RAM空间 2、已有的文件系…

luffy-(13)

内容概览 支付宝支付介绍支付宝支付二次封装订单相关表设计生成订单接口支付前端支付宝回调接口 支付宝支付介绍 """ 项目中有需要在线支付功能,可以使用支付宝支付(沙箱环境)微信支付(需要有备案过的域名)云闪付我们的项目以支付宝支付为例支付流程使用官方…

【FLFL】

论文记录 1. 3.3《基于区块链的联邦学习技术综述》2. 3.4《Swarm Learning for decentralized and confidential clinical machine learning》3. 3.8《Blockchained On-Device Federated Learning》4. 3.11《FLchain: Federated Learning via MEC-enabled Blockchain Network》…

LYF95101A 是一款高性能、高集成度、具有快速

LYF95101A 概述 LYF95101A是一款高性能、高集成度、具有快速 关断特性的单通道同步整流控制器。支持CCM, QR和 DCM的多模式工作。通过智能的控制MOSFET的开通 和关断&#xff0c;可替代反激变换器次级整流的肖特基二极管 来实现效率的提高。 LYF95101A 内置自供电电路&#xff…

渗透测试简介

病毒&#xff1a;是在计算机程序中插入的破坏计算机功能或者数据的代码&#xff0c;能影响计算机使用&#xff0c;能自我复制的一组计算机指令或者程序代码&#xff1b; ●木马&#xff1a;是比较流行的病毒文件&#xff0c;与一般的病毒不同&#xff0c;它不会自我繁殖&#x…

介绍模糊测试(Fuzz Testing,Fuzzing)

介绍模糊测试&#xff08;Fuzz Testing&#xff0c;Fuzzing&#xff09; 一、什么是模糊测试&#xff1f; 模糊测试是一种自动或半自动的测试技术&#xff0c;常被用来发现软件/操作系统/网络的代码中的错误和安全性问题&#xff0c;其中用于输入随机的数据和不合法的数据被称…

#学习笔记4#软件测试基础——测试阶段划分、黑盒测试的一些知识

今天主要看了以下几个方面的知识点&#xff0c;基本都是纯理论&#xff0c;本文只做知识点总结&#xff0c;具体内容要看转载 1.软件测试阶段划分&#xff0c;分为4个阶段&#xff1a;单元测试、集成测试、系统测试、验收测试 单元测试是方法类的覆盖&#xff0c;主要是由开…

辅助程序实现黑盒自动化测试的常见问题

背景 辅助程序&#xff08;Accessibility&#xff09;在大多数机型上具有重启设备后被激活的特性&#xff0c;可以完成Android测试框架&#xff08;Uiautomator1.0、Uiautomator2.0&#xff09;无法实现的功能。本文介绍如何搭建辅助程序和如何利用辅助程序进行黑盒测试。并总…

Android 13 Camera ITS 环境搭建(从Python安装到环境配置详解)

Python 版本 根据CameraITS.pdf 以及报错信息提示需要python版本在3.7.9及以上&#xff0c;本次使用的是3.8.10。 Python 安装 1.官方网站下载Python源码 wget https://www.python.org/ftp/python/3.8.10/Python-3.8.10.tgz 2.进入到下载路径&#xff0c;解压Python文件 …

黑盒测试常见错误类型说明及解决方法有哪些?

目录 1、用户界面错误 2、遗漏信息 3、错误的、误导的或令人迷惑的信息 1、用户界面错误 功能性 易用性&#xff08;用户学习使用程序的时间和记住怎样使用程序的时间&#xff09; 执行速度&#xff08;多数是启动速度&#xff0c;查询速度&#xff0c;刷新速度及响应速度…

浅析黑盒测试与白盒测试

这里写自定义目录标题 黑盒测试黑盒测试常见的测试&#xff1a;黑盒测试常用的方法&#xff1a;等价类划分&#xff1a;边界值分析&#xff1a;因果图分析法、错误推断法&#xff1a; 白盒测试白盒测试常见的方法&#xff1a; 黑盒测试与白盒测试的优缺点二者的优点二者的缺点 …

卸载symantec杀毒软件

(Get-WmiObject -Class Win32_Product -Filter “Name‘Symantec Endpoint Protection’” -ComputerName . ).Uninstall()

schrodinger 薛定谔安装与卸载

schrodinger 薛定谔安装 Windows 版 百度云 链接&#xff1a;https://pan.baidu.com/s/107a4KMHMvg1vrXTFHnGcWw 提取码&#xff1a;c6t4 安装步骤 download所有压缩包&#xff0c;解压任意一个压缩包即可&#xff08;压缩包之间是相互关联的&#xff09;。 进入解压的后的文…

从rookie到基佬~009:无密码卸载Symantec

今天是变直小技巧 今日份洗脑&#xff1a;无密码情况下卸载Symantec&#xff08;赛门铁克&#xff09; 结论&#xff1a;赛门铁克的服务一旦启动&#xff0c;怎么卸载都需要密码&#xff0c;反过来说&#xff0c;你不让他启动&#xff0c;他就是待宰的羔羊。 坐标国内某企业…

赛门铁克下载

Symantec&#xff08;赛门铁克&#xff09;杀毒软件&#xff0c;包括Symantec AntiVirus即SAV系列&#xff0c;Symantec Client Security即SCS系列&#xff0c;以及Symantec Endpoint Protection即SEP系列&#xff0c;都是专门为企业级用户定制的。这3套Symantec杀毒软件均包括…