Reputation: 31
I have implemented a polynomial curve fitting method in C++ OpenCV based on the fact that any function can be approximated with the power function. The equation is then written into matrix form and is being solved. Basically, the code is this:
PolynomialFit(std::vector<cv::Point>& points, int order) {
cv::Mat U(points.size(), (order + 1), CV_64F);
cv::Mat Y(points.size(), 1, CV_64F);
for (int i = 0; i < U.rows; i++) {
for (int j = 0; j < U.cols; j++) {
U.at<double>(i, j) = pow(points[i].x, j);
}
}
for (int i = 0; i < Y.rows; i++) {
Y.at<double>(i, 0) = points[i].y;
}
cv::Mat K((order + 1), 1, CV_64F);
if(U.data != NULL) {
K = (U.t() * U).inv() * U.t() * Y;
}
and in main this is how I call it:
int order = 2;
cv::Mat K = PolynomialFit(_points, order);
if(_points.size() > 0) {
for (int j = _points.at(0).x; j < _points.at(_points.size() - 1).x; j++) {
cv::Point2d point(j, 0);
for (int k = 0; k < order + 1; k++) {
point.y += K.at<double>(k, 0) * std::pow(j, k);
}
cv::circle(image, point, 1, cv::Scalar(0, 255, 0), CV_FILLED, CV_AA);
}
}
The problem is, it only works for a certain type of points. For example, in the image below, it only works for the points that are in the left curve. How could I change this behaviour? I already tried changing the order parameter, but the right curve won't fit as it should be.
Upvotes: 1
Views: 2691
Reputation: 1803
For calculating fit curve, it has to transform axis. As you see below, you can get 2 fit curves with horizontal x axis and vertical x axis, and then get the sum of erro power, select one curve which has minium sum.
For this, you can exchange x and y from your code of PolynomialFit function.
Upvotes: 2