我正在将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
向量的梯度。我希望我能正确解决我的问题,并希望获得一些提示。