Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save stiv-yakovenko/6062b09a0ad4667c55c3189b1671b1bd to your computer and use it in GitHub Desktop.
Save stiv-yakovenko/6062b09a0ad4667c55c3189b1671b1bd to your computer and use it in GitHub Desktop.
fit gauss with opencv Nelder–Mead method downhill solver
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/videoio.hpp"
#include <opencv2/calib3d.hpp>
#include <opencv2/core/cvstd.hpp>
#include <iostream>
using namespace cv;
using namespace std;
double my_exp(double a,double s, double x0,double x){
return a*exp(-pow(x-x0,2)/(2*s*s));
}
int main(){
vector<double> ys={0,0,0,0,0,1,2,3,6,8,7,5,2,1,0,0,0,1,0,0,0,0};
class Loss:public MinProblemSolver::Function{
public:
vector<double> ys;
Loss(vector<double> ys_):ys(ys_){}
int getDims() const { return 3; }
double calc(const double* params)const{
double a = params[0];
double s = params[1];
double x0 = params[2];
double sum=0;
for(int i=0;i<ys.size();i++){
sum+=pow(my_exp(a,s,x0,i)-ys[i],2);
}
return sum;
}
};
cv::Ptr<cv::MinProblemSolver::Function> ptr_F = cv::makePtr<Loss>(ys);
cv::Ptr<cv::DownhillSolver> solver=cv::DownhillSolver::create();
Mat step=(cv::Mat_<double>(3,1)<<0.05,0.05,.05);
Mat params=(cv::Mat_<double>(3,1)<<5,4,5);
step*=.0001;
solver->setInitStep(step);
solver->setFunction(ptr_F);
solver->minimize(params);
Mat img = Mat::zeros(300,300,CV_8UC3);
for(int x =0;x<img.cols;x++){
double xx=x;
double*prms=(double*)params.data;
double a = prms[0];
double s = prms[1];
double x0 = prms[2];
int y=my_exp(a,s,x0,x);
img.at<Vec3b>(y,x)=Vec3b(255,255,255);
if (x<ys.size()){
int y1 = ys[x];
img.at<Vec3b>(y1, x) = Vec3b(255, 0, 255);
}
}
imshow("img",img);
waitKey(0);
cout << "params"<<params;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment