如何在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> &params, vector<Point> &keypoint_index);
    MyPowell(Point2d &dst_br, vector<double> &params, Point2d & dims);
    MyPowell();
    double obj(vector<double> &params);

    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 ++中找到两个向量之间的最小(优化)距离的主要内容,如果未能解决你的问题,请参考以下文章

如何对图的节点进行排序,以使两个相邻节点之间的距离最小

如何在postgres中获得两个向量之间的余弦距离?

如何在 THREE.js 中找到两个向量之间的旋转矩阵

给定两个区域的经度和纬度,如何找到它们之间的距离(以米为单位)。如何在 SQL 中查询..?

如何找到地图中两个地理点之间的正确距离?

如何在opencv中找到单个图像的关键点之间的欧几里得距离