"); //-->
在自动驾驶系统中,通常会用起点、终点和一个三阶多项式来表示一条车道线,多项式系数的求解一般用最小二乘法来实现。
本文首先介绍两种基于最小二乘法的多项式拟合方法的原理,然后基于OpenCV用c++编写了这两种拟合方法的代码,最后通过一个完整的示例来展示如何通过一个离散点集拟合出一条多项式曲线。
基于最小二乘法的多项式拟合原理推导代数方式求解多项式曲线拟合是指基于一系列的观测点去寻找一个多项式来表示这些点的关系,最小二乘法通过最小化误差的平方和去寻找数据的最佳匹配函数。假设有点集
其中,和的关系满足函数
假设次多项式函数为
其中为多项式系数。如果要用这个次多项式来表示与的关系,那么多项式值与真实值之间的误差为
采用最小二乘法进行多项式拟合的目的就是寻找一组最佳的多项式系数使得拟合后整个点集的总误差最小,而求总误差最小的问题可以转化为求误差平方和最小。整个点集的误差平方和为
要使最小,可以对()求偏导并令其为零:
可得
写成矩阵形式可得
把上式写为,那么只要计算出
和
,再代入上面的式子中构建出矩阵和,那么多项式系数就可以通过求解线性方程组得到。
矩阵方式求解从上一节的推导过程可以看到,用代数法求解多项式系数的方法非常繁琐而且计算量比较大,我们其实还可以用矩阵求解的方法来简化计算过程。
令
那么整个点集的误差平方和可以表示为
对求导可得
令导数为零,那么可以得到
解得
学习了前面的理论知识,我们用c++来编码实现一下,毕竟光看一堆数学公式还是不够直观。从前面的理论知识可以知道,用最小二乘法做多项式曲线拟合其实质就是一个矩阵求解的问题,我们可以借助一些常用的数学库比如OpenCV或Eigen来求解。本文将采用OpenCV来实现。
1. 代数方式求解的C++代码实现如果理解了前面的理论,写代码其实就比较简单了。对照前面理论部分的公式,构建好矩阵A和B,然后调用OpenCV的solve()函数来求解即可:
// 代数方式求解2. 矩阵方式求解的C++代码实现
void PolyFit(const std::vector<cv::Point2f> &points, const int order,
cv::Mat *coeff) {
const int n = points.size();
cv::Mat A = cv::Mat::zeros(order + 1, order + 1, CV_64FC1);
cv::Mat B = cv::Mat::zeros(order + 1, 1, CV_64FC1);
// 构建A矩阵
for (int i = 0; i < order + 1; ++i) {
for (int j = 0; j < order + 1; ++j) {
for (int k = 0; k < n; ++k) {
A.at<double>(i, j) += std::pow(points.at(k).x, i + j);
}
}
}
// 构建B矩阵
for (int i = 0; i < order + 1; ++i) {
for (int k = 0; k < n; ++k) {
B.at<double>(i, 0) += std::pow(points.at(k).x, i) * points.at(k).y;
}
}
(*coeff) = cv::Mat::zeros(order + 1, 1, CV_64FC1);
// 求解
if (!cv::solve(A, B, *coeff, cv::DECOMP_LU)) {
std::cout << "Failed to solve !" << std::endl;
}
}
矩阵方式求解的代码更加简单:
// 矩阵方式求解3. 一个完整的多项式曲线拟合示例
void PolyFit(const std::vector<cv::Point2f> &points, const int order,
cv::Mat *coeff) {
const int n = points.size();
cv::Mat A = cv::Mat::ones(n, order + 1, CV_64FC1);
cv::Mat B = cv::Mat::zeros(n, 1, CV_64FC1);
for (int i = 0; i < n; ++i) {
const double a = points.at(i).x;
const double b = points.at(i).y;
B.at<double>(i, 0) = b;
if (i > 0) {
for (int j = 1, v = a; j < order + 1; ++j, v *= a) {
A.at<double>(i, j) = v;
}
}
}
(*coeff) = (A.t() * A).inv() * A.t() * B;
}
接下来,我们来看一个简单的曲线拟合示例:
int main(int argc, char **argv) {
constexpr int kOrder = 3; // 多项式阶数
constexpr int kWidth = 1000;
constexpr int kHeight = 500;
cv::Mat canvas =
cv::Mat(cv::Size(kWidth, kHeight), CV_8UC3, cv::Scalar(255, 255, 255));
cv::RNG rng(0xFFFFFFFF); // 随机数
// 生成点集,y坐标添加一些随机噪声
std::vector<cv::Point2f> raw_points;
for (int i = 10; i < kWidth; i += 10) {
cv::Point2f p;
p.x = i;
const auto noise = rng.uniform(-kHeight / 10, kHeight / 10);
p.y = kHeight - p.x / kWidth * kHeight + noise;
cv::circle(canvas, p, 5, cv::Scalar(0, 0, 255), -1);
raw_points.emplace_back(p);
}
// 多项式拟合
cv::Mat coeff;
PolyFit(raw_points, kOrder, &coeff);
// 用拟合后的系数重新生成点集
std::vector<cv::Point> poly_points;
for (const auto &rp : raw_points) {
cv::Point p;
p.x = rp.x;
p.y = PolyValue(coeff, kOrder, rp.x);
cv::circle(canvas, p, 5, cv::Scalar(0, 255, 0), -1);
poly_points.emplace_back(p);
}
cv::polylines(canvas, poly_points, false, cv::Scalar(0, 255, 0), 3,
cv::LINE_4);
cv::imshow("PolyFit", canvas);
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}
代码的流程如下:
其中用于计算多项式值的函数PolyValue()实现如下:
float PolyValue(const cv::Mat &coeff, const int order, const float x) {
float v = 0;
for (int i = 0; i < order; ++i) {
v += coeff.at<double>(i, 0) * std::pow(x, i);
}
return v;
}
可视化的结果如下图所示,其中红色点为原始点,绿色点为拟合后的点。
本文详细介绍了基于最小二乘法的多项式拟合的原理和代码实现,希望对各位读者有所帮助。如果对本文内容有疑问,欢迎评论区留言与我交流。
专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们
相关推荐
万家乐JSYZ5-AI燃气热水器电路图
基于Microchip MCU的AI/ML培训教程3
EEPW2018年6月刊(5G)
基于Microchip MCU的AI/ML培训教程2
研华 COMPUTEX 首度整合全球伙伴大会 强化全球边缘 AI 生态系统联结
Nigel AI赋能LabVIEW,NI用AI重塑测试新边界
爱立信携手 Net Feasa 布局海事网络 融合公网级通信与智能体 AI 赋能航运
继上次海联达Ai-ap100拆机之电源改造
基于Ai-WB2-12F与Rd-04的雷达检测系统
紧凑型集成连接器模块抑制噪声 为人工智能应用实现以太网供电
释说芯语16:硬科技:构建企业未来之路(附PPT)
人工智能是如何帮助阻止造假者的?
赋能边缘端对话式人工智能
英伟达CFO:我们早就知道内存大涨价要来了
EEPW2018年3月刊(工业物联网)
GPU:面临工作负载转变的高吞吐架构
瑞萨电子AI单元解决方案成功提高GE医疗(日本)日野工厂的生产力
WTC-AI太阳能热水器电路图
AI竞争进入下半场:从“卷参数”到“卷单价”
AI热潮引发多层陶瓷电容MLCC供应短缺
电子元件培训教材
尼吉康的事业介绍
iCAN-4017 AI功能模块
WTC-AI型太阳能热水器电路图
CSR8670CSR8675智能语音Alexa蓝牙方案开发
PowiGaN for AI Data Centers: Unmatched Power Density and Reliability
海联达(Aigale)Ai-HD1 无线全高清套件拆解
基于Microchip MCU的AI/ML培训教程1
基于VisitionX制造智能眼镜
AI 驱动估值飙升:光通信半导体企业市值暴涨