一,拟合效果图
曲线拟合,另外画了折线图
直线拟合
二,源码
//开始
void CLeastSquaresMethodDlg::OnBnClickedStartButton()
{
//创建用于绘制的深蓝色背景图像
int i_pointNum = 12;
cv::Mat image = cv::Mat::zeros(480, 640, CV_8UC3);
image.setTo(cv::Scalar(0, 100, 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.));
points.push_back(cv::Point(400., 458.));
points.push_back(cv::Point(153., 79.));
points.push_back(cv::Point(240., 110.));
points.push_back(cv::Point(272., 170.));
points.push_back(cv::Point(330., 260.));
points.push_back(cv::Point(380., 460.));
//将拟合点绘制到空白图上
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(255, 0, 0), 2, 8, 0);
cv::Mat A;
//多项式拟合曲线
polynomial_curve_fit(points, 3, A);
//fitLine(points, A, CV_DIST_L2, 0, 0.01, 0.01);
//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);
//#####直线拟合#####################################################################
float d, t;
Mat img2 = Mat::zeros(480, 640, CV_8UC3);
img2.setTo(cv::Scalar(0, 100, 0));
Mat pointMat2 = Mat(1, i_pointNum, CV_32FC1);
// find the optimal line 曲线拟合
fitLine(points, pointMat2, CV_DIST_L1, 1, 0.001, 0.001);
float x0 = pointMat2.at<float>(0,0);
float y0 = pointMat2.at<float>(1,0);
float x1 = pointMat2.at<float>(2,0);
float y1 = pointMat2.at<float>(3,0);
//画出点
for (int i = 0; i < i_pointNum; i++)
{
circle(img2, points[i], 5, cv::Scalar(0, 0, 255), 2, 8, 0);
}
// 延长线至图像两端
d = 1; //line[0 & 1]存储的是单位向量,所以d=1
//printf("\n %f\n", d);
//pointMat2.at<0, 0> /= d;
//pointMat2.at<0, 0> /= d;
//画出线段的两个端点(避免线太短,以线上一个随机点向两侧延伸line[0]*t )
Point pt1, pt2;
t = (float)(img2.cols + img2.rows);
pt1.x = cvRound(pointMat2.at<float>(2, 0) - pointMat2.at<float>(0, 0) * t);
pt1.y = cvRound(pointMat2.at<float>(3, 0) - pointMat2.at<float>(1, 0) * t);
pt2.x = cvRound(pointMat2.at<float>(2, 0) + pointMat2.at<float>(0, 0) * t);
pt2.y = cvRound(pointMat2.at<float>(3, 0) + pointMat2.at<float>(1, 0) * t);
//产生线
//MyLine(img2, Point(points2[0].x, points2[0].y), Point(points2[5].x, points2[5].y));
//line(img2,Point(points[1].x, points[1].y),Point(points[4].x, points[4].y),Scalar(0, 255, 0),2,8);
line(img2, Point(pt1.x, pt1.y), Point(pt2.x, pt2.y), Scalar(0, 255, 0), 2, 8);
imshow("直线拟合", img2);
//#####直线拟合#####################################################################
waitKey(0);
//cvDestroyWindow("直线拟合");
DestroyWindow();
//return 0;
}