I am trying to fit my vector which contains about 600 data points to a exponential decay function. I am using OpenCV 4.5.5 on ubuntu and I would like to obtain the index value i.e. the exponential decay constant from my data points. Here is an example with the GNU Scientific Library (GSL), it uses nonlinear least squares iteration, https://www.gnu.org/software/gsl/doc/html/nls.html#exponential-fitting-example It should work but I wonder if similar function/solution exisits with OpenCV? How can I use the fitline() and any curve fitting example?
Thanks, rolly
Alternatively, I found an opencv solution with Support Vector Regression (SVR), can anyone help me to extract the decay constant from the following code?
// draw some samples from exponential decay function and do a non-linear regression
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::ml;
// the sinc function
float sinc(float x)
{
return static_cast<float>( x==0 ? 1.0 : sin(x) / x );
}
int main(int argc, char* argv[])
{
RNG rng;
int ndata = 30;
Mat traindata(ndata, 1, CV_32FC1); // train data
Mat label(ndata, 1, CV_32FC1); // train response
for (int i = 0; i < ndata; ++i)
{
traindata.at<float>(i, 0) = static_cast<float>(i);
float noise = static_cast<float>(rng.gaussian(0.05));
//noise = 0.0; // uncomment to eliminate the noise
label.at<float>(i, 0) = static_cast<float>(exp(-i*0.25) + noise);
}
// show the train data
int width = 800;
int height = 600;
Mat canvas(height, width, CV_8UC3, Scalar(0,0,0));
double minV;
double maxV;
Point minId;
Point maxId;
minMaxLoc(traindata, &minV, &maxV, &minId, &maxId);
float X_shift = static_cast<float>(minV);
float X_ratio = static_cast<float>(width) / static_cast<float>(maxV - minV);
minMaxLoc(label, &minV, &maxV, &minId, &maxId);
float Y_shift = static_cast<float>(minV);
float Y_ratio = static_cast<float>(height) / static_cast<float>(maxV - minV);
for (int idx = 0; idx < traindata.rows; ++idx)
{
float x = (traindata.at<float>(idx, 0) - X_shift) * X_ratio;
float y = static_cast<float>(height) - (label.at<float>(idx, 0) - Y_shift) * Y_ratio;
circle(canvas, Point2f(x, y), 3, Scalar(0,0,255), -1);
}
imshow("train", canvas);
//imwrite("train_noise.png", canvas);
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::EPS_SVR);
svm->setKernel(SVM::RBF);
svm->setC(5);
svm->setP(1e-3);
svm->setGamma(0.01);
Ptr<TrainData> tData = TrainData::create(traindata, ROW_SAMPLE, label);
svm->train(tData);
// predict the responses of the samples and show them
for (float i = 0; i < ndata; i+=0.23f)
{
Mat sample(1,1, CV_32FC1);
sample.at<float>(0, 0) = static_cast<float>(i);
float response = svm->predict(sample);
//cout<<response<<endl;
float x = (sample.at<float>(0, 0) - X_shift) * X_ratio;
float y = static_cast<float>(height) - (response - Y_shift) * Y_ratio;
circle(canvas, Point2f(x, y), 3, Scalar(0,255,0), -1);
}
imshow("predict", canvas);
//imwrite("regress.png", canvas);
waitKey(0);
return 0;
}