首页 > 其他分享 >RANSAC方法例子

RANSAC方法例子

时间:2023-06-25 20:00:58浏览次数:41  
标签:RANSAC const int 方法 float 例子 result selects points

RANSAC是一种常用的剔除数据中异常点的方法。本文以拟合圆为例展示RANSAC的工作方式。首先我们有一组点,假设内点的概率是p。我们要使RANSAC的成功率至少达到${ \eta=99.9\% }$,那么至少需要重复选择多少次样本?首先确定一个圆需要3个点,即每次选择随机选3个点,因此一次选择包含外点的概率是${ 1-p^{3} }$。那么N次选择中每次都包含外点的概率是${ \left( 1-p^{3} \right)^{N} }$。我们需要N次选择至少有一次全是内点的概率超过${ \eta }$,有:

$${ 1-\left( 1-p^{3} \right)^{N} \geqslant \eta }$$

解之得:

$${ N \geqslant \frac{ ln\left( 1-\eta \right) }{ ln\left( 1-p^{3} \right) } }$$

下面给出代码:

class Ransac
{
public:
    Ransac(int ifitNumber, float confidence = 0.995f);
    virtual ~Ransac() = default;
    int execute(vector<Point2f>& points);

protected:
    virtual void fitModel(const vector<Point2f>& selects, Mat& result) = 0;
    virtual float evalModel(const Mat& model, const Point2f& pt) = 0;

private:
    int fitNumber;
    int loopCount;
};

Ransac::Ransac(int ifitNumber, float confidence)
{
    fitNumber = ifitNumber;
    loopCount = logf(1 - confidence) / logf(1 - powf(0.7f, fitNumber));
}

int Ransac::execute(vector<Point2f>& points)
{
    std::random_device rd;
    std::mt19937 e(rd());
    int count = (int)points.size();
    int bestInner = 0;
    vector<Point2f> innerDots, outerDots;
    for (int i = 0; i < loopCount; i++)
    {
        for (int j = 0; j < fitNumber; j++)
        {
            std::uniform_int_distribution<int> dist(j, count - 1);
            int r = dist(e);
            std::swap(points[j], points[r]);
        }
        Mat result;
        fitModel(points, result);
        int inner = 0;
        vector<Point2f> dots, outs;
        dots.reserve(count);
        outs.reserve(count);
        for (auto& item : points)
        {
            float score = evalModel(result, item);
            if (score >= 0.5f)
            {
                inner++;
                dots.push_back(item);
            }
            else
            {
                outs.push_back(item);
            }
        }
        if (inner > bestInner)
        {
            bestInner = inner;
            innerDots = std::move(dots);
            outerDots = std::move(outs);
        }
    }
    innerDots.insert(innerDots.end(), outerDots.begin(), outerDots.end());
    points = std::move(innerDots);
    return bestInner;
}

class CircleRansac : public Ransac
{
public:
    CircleRansac(float ierror, float confidence = 0.995f);

protected:
    void fitModel(const vector<Point2f>& selects, Mat& result) override;
    float evalModel(const Mat& model, const Point2f& pt) override;

private:
    float error;
};

CircleRansac::CircleRansac(float ierror, float confidence) :
    Ransac(3, confidence)
{
    error = ierror;
}

//---------------------------------------------------------------------------------------
// 3点求圆
//---------------------------------------------------------------------------------------
void CircleRansac::fitModel(const vector<Point2f>& selects, Mat& result)
{
    result.create(3, 1, CV_32FC1);
    float a = selects[0].x - selects[1].x;
    float b = selects[0].y - selects[1].y;
    float c = selects[0].x - selects[2].x;
    float d = selects[0].y - selects[2].y;
    float e = ((selects[0].x * selects[0].x - selects[1].x * selects[1].x) -
        (selects[1].y * selects[1].y - selects[0].y * selects[0].y)) * 0.5f;
    float f = ((selects[0].x * selects[0].x - selects[2].x * selects[2].x) -
        (selects[2].y * selects[2].y - selects[0].y * selects[0].y)) * 0.5f;
    float cx = (e * d - b * f) / (a * d - b * c);
    float cy = (a * f - e * c) / (a * d - b * c);
    float r = sqrtf((cx - selects[0].x) * (cx - selects[0].x) + (cy - selects[0].y) * (cy - selects[0].y));
    result.at<float>(0) = cx;
    result.at<float>(1) = cy;
    result.at<float>(2) = r;
}

float CircleRansac::evalModel(const Mat& model, const Point2f& pt)
{
    float cx = model.at<float>(0);
    float cy = model.at<float>(1);
    float r = model.at<float>(2);
    float dist = fabs(sqrtf((cx - pt.x) * (cx - pt.x) + (cy - pt.y) * (cy - pt.y)) - r);
    return dist < error ? 1 : 0;
}

使用方法如下:

int main()
{
    vector<Point2f> points = { ... };
    CircleRansac ransac(2.0f);
    int innerCount = ransac.execute(points);
    if (innerCount < 4)
    {
        return -1;
    }
    points.erase(points.begin() + innerCount, points.end());
    // 现在points里都是内点
    return 0;
}

 

标签:RANSAC,const,int,方法,float,例子,result,selects,points
From: https://www.cnblogs.com/mengxiangdu/p/17413469.html

相关文章

  • 基于三维离散点插值的高度图方法
    在我读研时,导师的项目是做一个无人水质检测船。其目标之一是具备绘制水域的深度图的功能。基本流程是在调查水域时用无人船载着一个深度计记录水域各处的位置和深度${\left(x,y,z\right)}$,然后根据测得的数据用LabView渲染成一个水域深度3D图。因为无人船测量深度数据的位置${......
  • 事务超时异常:org.springframework.transaction.TransactionTimedOutException: Transa
    报错如下:代码如下:Controllerimportcom.zwh.service.impl.TimeOutService;importlombok.extern.slf4j.Slf4j;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.w......
  • 关于Java中ArrayList类的toArray方法详解
    先上源码:publicObject[]toArray(){returnArrays.copyOf(elementData,size);}可以看到ArrayList类的toArray()方法调用了Arrays.copyOf(elementData,size)(其中的elementData是ArrayList类中用来存储对象的数组,size是数组大小),接下来进入其内部:publicsta......
  • Python动态修改实例对象的方法
    代码如下:importtypes#定义一个类classMyClass:deforiginal_method(self):#原始的执行函数print("原始的执行函数")#创建类的实例my_object=MyClass()#定义新的执行函数defnew_function(self):#在这里定义新的执行函数prin......
  • 集成AMD Xilinx的standalone的例子到FreeRTOS时,关于中断的注意事项
    集成AMDXilinx的standalone的例子到FreeRTOS时,关于中断的注意事项。FreeRTOS也可以说是standalone的程序。因此可以方便的把AMDXilinx的standalone的例子,集成到FreeRTOS。但是对于中断的处理,要小心。FreeRTOS会初始化中断控制器。对于使用中断模式的standalone的程序,也会初始......
  • 根据SPN和FMI生成DTC的方法
    做事情,记着抓主要矛盾,不可能面面俱到 =DEC2BIN(MOD(QUOTIENT(A1,256^2),256),8)&DEC2BIN(MOD(QUOTIENT(A1,256^1),256),8)&DEC2BIN(MOD(QUOTIENT(A1,256^0),256),8) 这个函数的意思就是把表格A1里面的数据全部搞成二进制例如A1里面是十进制520702 =DEC2BIN(D43,5) ......
  • 前端封装excel下载方法&&解决前端下载请求设置responseType: 'blob'时后台报错无法处
    请求设置responseType:'blob'时接口报错了如果不做处理则获取不到接口错误信息,此时下载的文件是有问题的。/*@paramsoptions{}*data:Blob,*fileName:String,*successMsg:String,**/import{Message}from'element-ui'importdownloadExcelFilePublicHandler......
  • 【vim】复制黏贴的方法
    1、按字符复制与粘贴在命令行模式下输入字符v(小写),便可以进入按字符选择模式,通过h、j、k、l键移动光标选择要进行复制的字符串。完成选择后按下y键进行复制,将鼠标移动到最后一行,按下p执行粘贴操作就完成了对选择的字符串部分完成了按字符复制与粘贴操作。按下小写v进入visual模......
  • 【pycharm】替换字符串的三种方法
    一、场景  工作中我们可能需要修改一些字符串为同一字符串,此时pycharm的一些替换功能就很好用 二、快捷键1、基于当前文件CTRL+R2、基于全局的替换 CTRL+SHIFT+R  三、替换的三种方法1、基于Cc的字符串 这种最简单,就是简单的替换某个字符串为另一个,可以......
  • git配置和上传方法
    1.配置用户名和邮箱:gitconfig--globaluser.name"your_name"gitconfig--globaluser.email"your_email"2.生成SSHkeyssh-keygen-trsa-C"your_email"接下来会有三次输入,都敲回车置为空。3.查看自己的公钥cat~/.ssh/id_rsa.pub从ssh-rsa开头,全部复制......