如何计算目标函数w.r.t参数的导数以最大程度地减少重投影误差

时间:2019-04-23 18:21:24

标签: c++ opencv matrix optimization derivative

我正在将Python的'page_dewarper'(https://mzucker.github.io/2016/08/15/page-dewarping.html)版本转换为C ++。我想计算一个重新投影误差度量-投影的3D点(ppts)和2D特征点(dstpoints)之间的平方距离之和。我的目标函数如下所示:

    // objective
    double suma = 0.0;
    for (int i=0; i<dstpoints.size(); i++) {
        suma += pow(dstpoints[i].x - ppts[i].x, 2);
        suma += pow(dstpoints[i].y - ppts[i].y, 2);
    }
    return suma;

,其中ppts是具有投影点的向量。向量ppts取决于参数(向量params)。 params向量包含以下信息:输出旋转向量,输出平移向量,图像关键点的坐标:

    // parameters
    std::vector<double> params_vector;

    for(int i = 0; i < rvec.rows; i++)
        params_vector.push_back(rvec.at<float>(0, i));

    for(int i = 0; i < tvec.rows; i++)
        params_vector.push_back(tvec.at<float>(0, i));

    for(auto cs : cubic_slopes)
        params_vector.push_back(cs);

    for(auto yc : ycoords)
        params_vector.push_back(yc);

    for(auto xcv : xcoords) {
        span_counts.push_back(xcv.size());
        for(auto xc : xcv)
            params_vector.push_back(xc);
    }

我可以为原始图像计算params向量,而我的问题是如何更改params向量的元素以获得与向量{{1}尽可能近的向量ppts }。向量dstpoints的构建方式如下:

ppts

我尝试了很少的无导数算法,这些算法主要来自dlib(http://dlib.net/optimization.html),但是它们很慢,或者收敛到局部最小值。我得到建议,应该计算我的目标函数w.r.t参数( // calculating ppts vector std::vector<double> keypoint_index; // values don't change int number_of_rows = keypoint_index.size(); std::vector<double> xy_coords; for(int i=0; i<number_of_rows; i++) xy_coords.push_back(params[keypoint_index[i]] ); xy_coords[0] = 0; xy_coords[number_of_rows/2] = 0; double alpha = params[6]; double beta = params[7]; std::vector<double> poly { alpha + beta, -2*alpha - beta, alpha, 0}; std::vector<cv::Point3f> objectPoints; int number_of_rows = xy_coords.size() / 2; for(int i=0; i<number_of_rows; i++) { objectPoints.push_back( cv::Point3f( xy_coords[i], xy_coords[i + number_of_rows], poly[0]*pow(xy_coords[i], 3) + poly[1]*pow(xy_coords[i], 2) + poly[2]*xy_coords[i] + poly[3])); } cv::Mat distCoeffs = cv::Mat::zeros(1, 5, CV_32FC1); std::vector<cv::Point2f> ppts; // default intrinsic parameter matrix cv::Mat K = cv::Mat(3, 3, CV_32FC1); K.at<float>(0,0) = FOCAL_LENGTH; K.at<float>(0,1) = 0.0; K.at<float>(0,2) = 0.0; K.at<float>(1,0) = 0.0; K.at<float>(1,1) = FOCAL_LENGTH; K.at<float>(1,2) = 0.0; K.at<float>(2,0) = 0.0; K.at<float>(2,1) = 0.0; K.at<float>(2,2) = 1.0; cv::Mat rvec_sliced = (cv::Mat_<double>(3,1) << params[0] , params[1], params[2] ); cv::Mat tvec_sliced = (cv::Mat_<double>(3,1) << params[3] , params[4], params[5] ); cv::projectPoints(objectPoints, rvec_sliced, tvec_sliced, K, distCoeffs, ppts); // now, I have ppts calculated 矢量)的梯度。归结为找到params向量相对于ppts向量的梯度。我希望我能正确解决我的问题,并希望获得一些提示。

0 个答案:

没有答案