Как рассчитать производную целевой функции по параметрам, чтобы минимизировать ошибку перепроецирования - PullRequest
0 голосов
/ 23 апреля 2019

Я перевожу версию 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 зависит от параметров (vector 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, чтобы получить вектор ppts, максимально приближенный к вектору dstpoints. Вектор ppts построен следующим образом:

    // 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

Я пробовал несколько без производныхалгоритмы, в основном из dlib (http://dlib.net/optimization.html),, но они медленные или сходятся к локальному минимуму. Я получил предложение, что мне следует рассчитать градиент моей целевой функции по параметрам (params вектор).Это сводится к нахождению градиента вектора ppts относительно вектора params.Надеюсь, я правильно разъяснил свою проблему и надеюсь на несколько советов.

...