仿射变换OpenCV实现的最小二乘优化

来源:互联网 发布:mac软件意外退出 编辑:程序博客网 时间:2024/05/21 06:26

仿射变换OpenCV实现的最小二乘优化

本文由 @lonelyrains出品,转载请注明出处。 
文章链接: http://blog.csdn.net/lonelyrains/article/details/49865683

// opencv中关于仿射变换的实现代码:cv::Mat cv::getAffineTransform( const Point2f src[], const Point2f dst[] ){    Mat M(2, 3, CV_64F), X(6, 1, CV_64F, M.ptr());    double a[6*6], b[6];    Mat A(6, 6, CV_64F, a), B(6, 1, CV_64F, b);    for( int i = 0; i < 3; i++ )    {        int j = i*12;        int k = i*12+6;        a[j] = a[k+3] = src[i].x;        a[j+1] = a[k+4] = src[i].y;        a[j+2] = a[k+5] = 1;        a[j+3] = a[j+4] = a[j+5] = 0;        a[k] = a[k+1] = a[k+2] = 0;        b[i*2] = dst[i].x;        b[i*2+1] = dst[i].y;    }    solve( A, B, X );    return M;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

本函数只接受三个点的仿射变换,并不能处理样本点超过三个点、需要用最小二乘来找最接近的仿射变换的方式,所以笔者修改了本函数的实现,重新定义了一个如下:

// 仿射变换模型,线性回归,正规方程求解参数矩阵的方法cv::Mat myGetAffineTransform(const cv::Point2f src[], const cv::Point2f dst[], int m){    cv::Mat_<float> X = cv::Mat(m, 3, CV_32FC1, cv::Scalar(0));    cv::Mat_<float> Y = cv::Mat(m, 2, CV_32FC1, cv::Scalar(0));    for (int i = 0; i < m; i++)    {        float x0 = src[i].x, x1 = src[i].y;        float y0 = dst[i].x, y1 = dst[i].y;        X(i, 0) = x0;        X(i, 1) = x1;        X(i, 2) = 1;        Y(i, 0) = y0;        Y(i, 1) = y1;    }    cv::Mat_<float> F = (X.t()*X).inv()*(X.t()*Y);    // cout << F << endl;    return F.t();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

本实现是基于最小二乘的正规矩阵方法求解。正好与之前的一篇机器学习的文章呼应。可以参考:机器学习(四)正规方程求解线性回归问题、正规方法与梯度法的优劣

原创粉丝点击