Я перевожу версию 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
.Надеюсь, я правильно разъяснил свою проблему и надеюсь на несколько советов.