自动驾驶工具箱-车道保持辅助与车道检测

最小二乘法多项式曲线拟合,是常见的曲线拟合方法,有着广泛的应用,这里在借鉴最小二乘多项式曲线拟合原理与实现的原理的基础上,介绍如何在OpenCV来实现基于最小二乘的多项式曲线拟合。

概念

最小二乘法多项式曲线拟合,根据给定的m个点,并不要求这条曲线精确地经过这些点,而是曲线y=f(x)的近似曲线y= φ(x)。

原理

给定数据点pi(xi,yi),其中i=1,2,…,m。求近似曲线y= φ(x)。并且使得近似曲线与y=f(x)的偏差最小。近似曲线在点pi处的偏差δi= φ(xi)-y,i=1,2,...,m。

常见的曲线拟合方法:

1.使偏差绝对值之和最小

2.使偏差绝对值最大的最小
     

3.使偏差平方和最小

按偏差平方和最小的原则选取拟合曲线,并且采取二项式方程为拟合曲线的方法,称为最小二乘法。

推导过程:

1. 设拟合多项式为:

2.各点到这条曲线的距离之和,即偏差平方和如下:

3.为了求得符合条件的a值,对等式右边求ai偏导数,因而我们得到了:

.......

4.将等式左边进行一下化简,然后应该可以得到下面的等式:

.......

5.把这些等式表示成矩阵的形式,就可以得到下面的矩阵:

6.即X*A=Y。

我们只要解出这个线性方程,即可求得拟合曲线多项式的系数矩阵。而在opencv中,有一个专门用于求解线性方程的函数,即cv::solve(),具体调用形式如下:

    int cv::solve(cv::InputArray X, // 左边矩阵X, nxncv::InputArray Y, // 右边矩阵Y,nx1cv::OutputArray A, // 结果,系数矩阵A,nx1int method = cv::DECOMP_LU // 估算方法);

我们只需要按照上述原理,构造出矩阵X和Y,即可调用该函数,计算出多项式的系数矩阵A。

opencv中支持的估算方法如下图所示:

实现如下:

bool polynomial_curve_fit(std::vector<cv::Point>& key_point, int n, cv::Mat& A){//Number of key pointsint N = key_point.size();//构造矩阵Xcv::Mat X = cv::Mat::zeros(n + 1, n + 1, CV_64FC1);for (int i = 0; i < n + 1; i++){for (int j = 0; j < n + 1; j++){for (int k = 0; k < N; k++){X.at<double>(i, j) = X.at<double>(i, j) +std::pow(key_point[k].x, i + j);}}}//构造矩阵Ycv::Mat Y = cv::Mat::zeros(n + 1, 1, CV_64FC1);for (int i = 0; i < n + 1; i++){for (int k = 0; k < N; k++){Y.at<double>(i, 0) = Y.at<double>(i, 0) +std::pow(key_point[k].x, i) * key_point[k].y;}}A = cv::Mat::zeros(n + 1, 1, CV_64FC1);//求解矩阵Acv::solve(X, Y, A, cv::DECOMP_LU);return true;}

测试代码如下:

 int main(){//创建用于绘制的深蓝色背景图像cv::Mat image = cv::Mat::zeros(480, 640, CV_8UC3);image.setTo(cv::Scalar(100, 0, 0));//输入拟合点  std::vector<cv::Point> points;points.push_back(cv::Point(100., 58.));points.push_back(cv::Point(150., 70.));points.push_back(cv::Point(200., 90.));points.push_back(cv::Point(252., 140.));points.push_back(cv::Point(300., 220.));points.push_back(cv::Point(350., 400.));//将拟合点绘制到空白图上  for (int i = 0; i < points.size(); i++){cv::circle(image, points[i], 5, cv::Scalar(0, 0, 255), 2, 8, 0);}//绘制折线cv::polylines(image, points, false, cv::Scalar(0, 255, 0), 1, 8, 0);cv::Mat A;polynomial_curve_fit(points, 3, A);std::cout << "A = " << A << std::endl;std::vector<cv::Point> points_fitted;for (int x = 0; x < 400; x++){double y = A.at<double>(0, 0) + A.at<double>(1, 0) * x +A.at<double>(2, 0)*std::pow(x, 2) + A.at<double>(3, 0)*std::pow(x, 3);points_fitted.push_back(cv::Point(x, y));}cv::polylines(image, points_fitted, false, cv::Scalar(0, 255, 255), 1, 8, 0);cv::imshow("image", image);cv::waitKey(0);return 0;}

绘制结果:

cv::solve(X, Y, A, cv::DECOMP_LU);

A = [-80.59143874478204;
 2.591187861030039;
 -0.01564864659563801;
 3.472543637058225e-05]

cv::solve(X, Y, A, cv::DECOMP_SVD)

A = [0.02079552657076436;
 1.342995408381021;
 -0.009847461533329421;
 2.641160332074949e-05]

cv::solve(X, Y, A, cv::DECOMP_CHOLESKY);

A = [-80.59143874468819;
 2.591187861028489;
 -0.01564864659563045;
 3.472543637057102e-05]

车道检测

OpenCV曲线拟合与圆拟合

使用OpenCV做图像处理与分析的时候,经常会遇到需要进行曲线拟合与圆拟合的场景,很多OpenCV开发者对此却是一筹莫展,其实OpenCV中是有现成的函数来实现圆拟合与直线拟合的,而且还会告诉你拟合的圆的半径是多少,简直是超级方便,另外一个常用到的场景就是曲线拟合,常见的是基于多项式拟合,可以根据设定的多项式幂次生成多项式方程,然后根据方程进行一系列的点生成,形成完整的曲线,这个车道线检测,轮廓曲线拟合等场景下特别有用。下面就通过两个简单的例子来分别学习一下曲线拟合与圆拟合的应用。

一:曲线拟合与应用

基于Numpy包的polyfit函数实现,其支持的三个参数分别是x点集合、y点集合,以及多项式的幂次。得到多项式方程以后,就可以完整拟合曲线,图中有如下四个点:

调用polyfit生成的二阶多项式如下:

拟合结果如下:

使用三阶多项式拟合,调用polyfit生成的多项式方程如下:

生成的拟合曲线如下:

使用polyfit进行曲线拟合时候需要注意的是,多项式的幂次最大是数据点数目N - 1幂次多项式,比如有4个点,最多生成3阶多项式拟合。上述演示的完整代码实现如下:

def circle_fitness_demo():image = np.zeros((400, 400, 3), dtype=np.uint8)x = np.array([30, 50, 100, 120])y = np.array([100, 150, 240, 200])for i in range(len(x)):cv.circle(image, (x[i], y[i]), 3, (255, 0, 0), -1, 8, 0)cv.imwrite("D:/curve.png", image)poly = np.poly1d(np.polyfit(x, y, 3))print(poly)for t in range(30, 250, 1):y_ = np.int(poly(t))cv.circle(image, (t, y_), 1, (0, 0, 255), 1, 8, 0)cv.imshow("fit curve", image)cv.imwrite("D:/fitcurve.png", image)

二:圆拟合与应用

圆的拟合是基于轮廓发现的结果,对发现的近似圆的轮廓,通过圆拟合可以得到比较好的显示效果,轮廓发现与拟合的API分别为findContours与fitEllipse,
有图像如下:

使用轮廓发现与圆拟合处理结果如下:

红色表示拟合的圆,蓝色是圆的中心位置
上述完整的演示代码如下:

def circle_fitness_demo():src = cv.imread("D:/javaopencv/c2.png")cv.imshow("input", src)src = cv.GaussianBlur(src, (3, 3), 0)gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)cv.imshow("binary", binary)image, contours, hierachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)for i in range(len(contours)):rrt = cv.fitEllipse(contours[i])cv.ellipse(src, rrt, (0, 0, 255), 2, cv.LINE_AA)x, y = rrt[0]cv.circle(src, (np.int(x), np.int(y)), 4, (255, 0, 0), -1, 8, 0)cv.imshow("fit circle", src)cv.imwrite("D:/fitcircle.png", src)

参考:

【算法+OpenCV】基于opencv的直线和曲线拟合与绘制(最小二乘法)

OpenCV曲线拟合与圆拟合

【学习OpenCV】基于opencv的直线和曲线拟合与绘制(最小二乘法)相关推荐

  1. 【算法+OpenCV】基于opencv的直线和曲线拟合与绘制(最小二乘法)

    最小二乘法多项式曲线拟合,是常见的曲线拟合方法,有着广泛的应用,这里在借鉴最小二乘多项式曲线拟合原理与实现的原理的基础上,介绍如何在OpenCV来实现基于最小二乘的多项式曲线拟合. 概念 最小二乘法多 ...

  2. opencv 人脸识别_Python学习:基于Opencv来快速实现人脸识别(完整版)

    随着人工智能的日益火热,计算机视觉领域发展迅速,尤其在人脸识别或物体检测方向更为广泛,今天就为大家带来最基础的人脸识别基础,从一个个函数开始走进这个奥妙的世界. 首先看一下本实验需要的数据集,为了简便 ...

  3. 深度学习之基于opencv和CNN实现人脸识别

    这个项目在之前人工智能课设上做过,但是当时是划水用的别人的.最近自己实现了一下,基本功能可以实现,但是效果并不是很好.容易出现错误识别,或者更改了背景之后识别效果变差的现象.个人以为是数据选取的问题, ...

  4. OpenCV | 基于OpenCV的双目图像采集源代码(相机标定)

    博主github:https://github.com/MichaelBeechan 博主CSDN:https://blog.csdn.net/u011344545 ================= ...

  5. matlab fft2 opencv,基于OPENCV的FFT2变换

    // opencv.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include using namespace std; IplIma ...

  6. python实现人脸口罩检测(基于opencv和深度学习两种方法)

    人脸口罩检测GUI系统(基于opencv和深度学习两种方法对比) 由于疫情的影响,人脸口罩检测系统的开发成为很多人争相开发的一种算法.很多公司或者个人都开源了他们很多的代码或者SDK.大家在GitHu ...

  7. 语义分割:基于openCV和深度学习(二)

    语义分割:基于openCV和深度学习(二) Semantic segmentation in images with OpenCV 开始吧-打开segment.py归档并插入以下代码: Semanti ...

  8. 语义分割:基于openCV和深度学习(一)

    语义分割:基于openCV和深度学习(一) Semantic segmentation with OpenCV and deep learning 介绍如何使用OpenCV.深度学习和ENet架构执行 ...

  9. 【功能超全】基于OpenCV车牌识别停车场管理系统软件开发【含python源码+PyqtUI界面+功能详解】-车牌识别python 深度学习实战项目

    车牌识别基础功能演示 摘要:车牌识别系统(Vehicle License Plate Recognition,VLPR) 是指能够检测到受监控路面的车辆并自动提取车辆牌照信息(含汉字字符.英文字母.阿 ...

最新文章

  1. 一个简洁OKR是成功的关键因素
  2. android富文本图片自适应,Android Span富文本图文混排 - ImageSpan(图文垂直居中)...
  3. Mysql while 嵌套 cursor 游标, 数据迁移
  4. 数据挖掘学习笔记之人工神经网络(二)
  5. Chinese savior crepe
  6. Android APP层 ShellUtils
  7. CRM中间件里的CSA队列有什么用
  8. [react] React组件的构造函数是必须的吗?
  9. 较Win7企业更愿用Win10?原因就在这里
  10. js中数组filter过滤奇偶数_JS filter()方法:根据指定条件过滤数组元素
  11. android 字体加粗有阴影,Android TextView高级显示技巧实例小结
  12. Django信号量实现用户密码修改
  13. python查询手册_Python 手册
  14. redis复习(参考书籍redis设计与实现)
  15. 使用IAR软件的搜索快捷键出现中文繁体现象
  16. 无敌论坛_无敌分享网_无敌资源网|专注CG教程和素材分享
  17. 中国芯绝配:普华推全新龙芯3A3000操作系统
  18. fig r函数_R语言图形函数par()参数应用举例.pdf
  19. php chr 1,PHP chr()用法及代码示例
  20. EndNote简明教程(三分钟上手EndNote)

热门文章

  1. java web项目网上银行_网上银行java项目源代码(含最终文档)超棒!
  2. 24小时制时间转换成am、pm (或 上午、下午)
  3. 7-10 小H喜欢睡觉
  4. html待办事项表格代码,Go For It ,一个灵活的待办事项列表程序
  5. nginx域名访问的白名单配置梳理
  6. 实现聊天对话室(多人聊天)
  7. Beautiful Soup是干什么用的
  8. 一起做激光反光板(三)-EKF建图公式推导
  9. C# 使用SMS接口实现手机短信发送功能
  10. 怎么部署ChatGPT