如何在C ++中找到两个向量之间的最小(优化)距离
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在C ++中找到两个向量之间的最小(优化)距离相关的知识,希望对你有一定的参考价值。
我正在将Python的'page_dewarper'(https://mzucker.github.io/2016/08/15/page-dewarping.html)版本翻译成C ++。我将使用dlib,这是一个很棒的工具,它帮助我解决了一些优化问题。在Github repo(https://github.com/mzucker/page_dewarp/blob/master/page_dewarp.py)的第748行中,Matt使用Scipy的优化函数来找到两个向量之间的最小距离。我认为,我的C ++等价物应该是solve_least_squares_lm()或solve_least_squares()。我将举一个具体的例子进行分析。
我的数据:
a)dstpoints是一个带有OpenCV点的向量 - std::vector<cv::Point2f>
(在这个例子中我有162个点,它们没有变化),
b)ppts也是std::vector<cv::Point2f>
,大小与dstpoints相同。
std::vector<cv::Point2f> ppts = project_keypoints(params, input);
它取决于:
- dlib::column_vector
'输入'是2 * 162 = 324长并且没有变化,
- dlib::column_vector
'params'是189长并且它的值应该被改变以获得变量'suma'的最小值,如下所示:
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);
我正在寻找'params'向量,它会给我'suma'变量的最小值。最小二乘算法似乎是解决它的一个很好的选择:http://dlib.net/dlib/optimization/optimization_least_squares_abstract.h.html#solve_least_squares,但我不知道它对我的情况是否有益。
我想,我的问题是,对于每个不同的'params'向量,我得到不同的'ppts'向量,不仅是单个值,而且我不知道solve_least_squares
函数是否可以匹配我的例子。
我必须为每一点计算残差。我想,上面提到的链接中的'list'应该是这样的:
(ppts[i].x - dstpoints[i].x, ppts[i].y - dstpoints[i].y, ppts[i+1].x - dstpoints[i+1].x, ppts[i+1].y - dstpoints[i+1].y, etc.)
,'ppts'向量依赖于'params'向量,然后这个问题可以用最小二乘算法解决。我不知道如何使用这些假设创建data_samples,因为它需要每个样本使用dlib::input_vector
,如示例所示:http://dlib.net/least_squares_ex.cpp.html。
我在想吗?
这几天我也在做同样的事情。我的解决方案是自己写一个鲍威尔课程。它工作,但真的很慢。该程序在dewarping linguistics_thesis.jpg中需要2分钟。我不知道程序运行得如此缓慢的原因。也许是因为算法或代码有一些额外的循环。我是中国学生,我的学校只有java课程。因此,如果您在我的代码中找到一些额外的代码,这是正常的。这是我的鲍威尔课程。
using namespace std;
using namespace cv;
class MyPowell
public:
vector<vector<double>> xi;
vector<double> pcom;
vector<double> xicom;
vector<Point2d> dstpoints;
vector<double> myparams;
vector<double> params;
vector<Point> keypoint_index;
Point2d dst_br;
Point2d dims;
int N;
int itmax;
int ncom;
int iter;
double fret, ftol;
int usingAorB;
MyPowell(vector<Point2d> &dstpoints, vector<double> ¶ms, vector<Point> &keypoint_index);
MyPowell(Point2d &dst_br, vector<double> ¶ms, Point2d & dims);
MyPowell();
double obj(vector<double> ¶ms);
void powell(vector<double> &p, vector<vector<double>> &xi, double ftol, double &fret);
double sign(double a);// , double b);
double sqr(double a);
void linmin(vector<double> &p, vector<double> &xit, int n, double &fret);
void mnbrak(double & ax, double & bx, double & cx,
double & fa, double & fb, double & fc);
double f1dim(double x);
double brent(double ax, double bx, double cx, double & xmin, double tol);
vector<double> usePowell();
void erase(vector<double>& pbar, vector<double> &prr, vector<double> &pr);
;
#include"Powell.h"
MyPowell::MyPowell(vector<Point2d> &dstpoints, vector<double>& params, vector<Point> &keypoint_index)
this->dstpoints = dstpoints;
this->myparams = params;
this->keypoint_index = keypoint_index;
N = params.size();
itmax = N * N;
usingAorB = 1;
MyPowell::MyPowell(Point2d & dst_br, vector<double>& params, Point2d & dims)
this->dst_br = dst_br;
this->myparams.push_back(dims.x);
this->myparams.push_back(dims.y);
this->params = params;
this->dims = dims;
N = 2;
itmax = N * 1000;
usingAorB = 2;
MyPowell::MyPowell()
usingAorB = 3;
double MyPowell::obj(vector<double> &myparams)
if (1 == usingAorB)
vector<Point2d> ppts = Dewarp::projectKeypoints(keypoint_index, myparams);
double total = 0;
for (int i = 0; i < ppts.size(); i++)
double x = dstpoints[i].x - ppts[i].x;
double y = dstpoints[i].y - ppts[i].y;
total += (x * x + y * y);
return total;
else if(2 == usingAorB)
dims.x = myparams[0];
dims.y = myparams[1];
//cout << "dims.x " << dims.x << " dims.y " << dims.y << endl;
vector<Point2d> vdims = dims ;
vector<Point2d> proj_br = Dewarp::projectXY(vdims, params);
double total = 0;
double x = dst_br.x - proj_br[0].x;
double y = dst_br.y - proj_br[0].y;
total += (x * x + y * y);
return total;
return 0;
void MyPowell::powell(vector<double> &x, vector<vector<double>> &direc, double ftol, double &fval)
vector<double> x1;
vector<double> x2;
vector<double> direc1;
int myitmax = 20;
if(N>500)
myitmax = 10;
else if (N > 300)
myitmax = 15;
double fx2, t, fx, dum, delta;
fval = obj(x);
int bigind;
for (int j = 0; j < N; j++)
x1.push_back(x[j]);
int iter = 0;
while (true)
do
do
iter += 1;
fx = fval;
bigind = 0;
delta = 0.0;
for (int i = 0; i < N; i++)
direc1 = direc[i];
fx2 = fval;
linmin(x, direc1, N, fval);
if (fabs(fx2 - fval) > delta)
delta = fabs(fx2 - fval);
bigind = i;
if (2.0 * fabs(fx - fval) <= ftol * (fabs(fx) + fabs(fval)) + 1e-7)
erase(direc1, x2, x1);
return;
if (iter >= itmax)
cout << "powell exceeding maximum iterations" << endl;
return;
if (!x2.empty())
x2.clear();
for (int j = 0; j < N; j++)
x2.push_back(2.0*x[j] - x1[j]);
direc1[j] = x[j] - x1[j];
x1[j] = x[j];
myitmax--;
cout << fx2 << endl;
fx2 = obj(x2);
if (myitmax < 0)
return;
while (fx2 >= fx);
dum = fx - 2 * fval + fx2;
t = 2.0*dum*pow((fx - fval - delta), 2) - delta * pow((fx - fx2), 2);
while (t >= 0.0);
linmin(x, direc1, N, fval);
direc[bigind] = direc1;
double MyPowell::sign(double a)//, double b)
if (a > 0.0)
return 1;
else
if (a < 0.0)
return -1;
return 0;
double MyPowell::sqr(double a)
return a * a;
void MyPowell::linmin(vector<double>& p, vector<double>& xit, int n, double &fret)
double tol = 1e-2;
ncom = n;
pcom = p;
xicom = xit;
double ax = 0.0;
double xx = 1.0;
double bx = 0.0;
double fa, fb, fx, xmin;
mnbrak(ax, xx, bx, fa, fx, fb);
fret = brent(ax, xx, bx, xmin, tol);
for (int i = 0; i < n; i++)
xit[i] = (xmin * xit[i]);
p[i] += xit[i];
void MyPowell::mnbrak(double & ax, double & bx, double & cx,
double & fa, double & fb, double & fc)
const double GOLD = 1.618034, GLIMIT = 110.0, TINY = 1e-20;
double val, fw, tmp2, tmp1, w, wlim;
double denom;
fa = f1dim(ax);
fb = f1dim(bx);
if (fb > fa)
val = ax;
ax = bx;
bx = val;
val = fb;
fb = fa;
fa = val;
cx = bx + GOLD * (bx - ax);
fc = f1dim(cx);
int iter = 0;
while (fb >= fc)
tmp1 = (bx - ax) * (fb - fc);
tmp2 = (bx - cx) * (fb - fa);
val = tmp2 - tmp1;
if (fabs(val) < TINY)
denom = 2.0*TINY;
else
denom = 2.0*val;
w = bx - ((bx - cx)*tmp2 - (bx - ax)*tmp1) / (denom);
wlim = bx + GLIMIT * (cx - bx);
if ((bx - w) * (w - cx) > 0.0)
fw = f1dim(w);
if (fw < fc)
ax = bx;
fa = fb;
bx = w;
fb = fw;
return;
else if (fw > fb)
cx = w;
fc = fw;
return;
w = cx + GOLD * (cx - bx);
fw = f1dim(w);
else
if ((cx - w)*(w - wlim) >= 0.0)
fw = f1dim(w);
if (fw < fc)
bx = cx;
cx = w;
w = cx + GOLD * (cx - bx);
fb = fc;
fc = fw;
fw = f1dim(w);
else if ((w - wlim)*(wlim - cx) >= 0.0)
以上是关于如何在C ++中找到两个向量之间的最小(优化)距离的主要内容,如果未能解决你的问题,请参考以下文章