c++实现Dbscan、Gaussian、Grubbs、Ransac滤波算法

Dbscan:聚类滤波,通过聚类区分内点与外点进行滤波。

/**
 * @brief My_Dbscan
 * @param data_ori  待滤波数据,最终滤波后数据
 * @param Eps       核心点搜索半径
 * @param MinPts    核心点半径内点数阈值
 * @return
 */
bool My_Dbscan(vector<float> &data_ori,float Eps,int MinPts)
{
    data_Dbscan data_Dbscan_temp;
    vector<data_Dbscan> data, data_swp;

    // 数据迁移
    for(int i=0; i<data_ori.size(); i++)
    {
        data_Dbscan_temp.id = i;
        data_Dbscan_temp.data = data_ori.at(i);
        data.push_back(data_Dbscan_temp);
    }

    // 搜索核心点
    for(int i=0; i<data.size(); i++)
    {
        for(int j=i+1; j<data.size(); j++)
        {
            if(abs(data.at(i).data - data.at(j).data) < Eps)
            {
                data.at(i).num++;
                data.at(j).core_id = i;
                data.at(j).dataType = 2;
            }
        }
    }

    // 判断核心点
    for(int i=0; i<data.size(); i++)
    {
        if(data.at(i).num > MinPts)
        {
            data.at(i).dataType = 3;
        }
        data.at(i).num = 0;
    }

    // 核心点所属核心id合并
    int num = 0;
    for(int i=0; i<data.size(); i++)
    {
        if(data.at(i).dataType == 3 && data.at(i).num == 0)
        {
            num++;
            data.at(i).num = num;
            for(int j=i+1; j<data.size(); j++)
            {
                if(data.at(j).dataType == 3)
                {
                    if(abs(data.at(i).data - data.at(j).data) < Eps)
                    {
                        data.at(j).num = num;
                    }
                }
            }
        }

    }

    // 核心区域内点id合并
    for(int i=0; i<data.size(); i++)
    {
        if(data.at(i).dataType == 2)
        {
            data.at(i).num = data.at(data.at(i).core_id).num;
        }
    }

    // 滤波数据更新
    data_ori.clear();
    for(int i=0; i<data.size(); i++)
    {
        if(data.at(i).num > 0)
        {
            data_ori.push_back(data.at(i).data);
        }
    }

    if(!data.empty())
    {
        data.clear();
        vector<data_Dbscan> tmp;
        data.swap(tmp);		// 进行交换
    }

    return true;
}

Gaussian:高斯滤波,将时域转为频域进行滤波。

/**
 * @brief My_Gaussianfilter     一维高斯滤波
 * @param data                  输入一维数据
 * @param filter_size           滤波器大小,推荐使用奇数
 * @param sigma                 标准差
 * @return
 */
bool My_Gaussianfilter(vector<float> &data, int filter_size, double sigma)
{
    double GaussTemp[2*filter_size - 1];
    for(int i=0; i<2*filter_size - 1; i++)
    {
        GaussTemp[i] = exp(-pow((i+1-filter_size), 2)/pow(sigma, 2)/2)/sqrt(2*3.1415)/sigma;
    }

    double data_filter[data.size()];
    for(int i=filter_size-1; i<data.size()-filter_size; i++)
    {
        data_filter[i] = 0;
        for(int j=0; j<2*filter_size - 1; j++)
        {
            data_filter[i] = data_filter[i] + data.at(i-filter_size+1+j) * GaussTemp[j];
        }
    }

    for(int i=0; i<data.size(); i++)
    {
        if(i>=filter_size && i<=data.size()-filter_size-1)
        {
            data.at(i) = data_filter[i];
        }
    }

    return true;
}

Grubbs:原理

// 格拉布斯表
double table[] = {  0.0,0.0,0.0,1.153,1.463,1.672,1.822,1.938,2.032,2.110,2.176,
                    2.234,2.285,2.331,2.371,2.409,2.443,2.475,2.501,2.532,2.557,
                    2.580,2.603,2.624,2.644,2.663,2.681,2.698,2.714,2.730,2.745,
                    2.759,2.773,2.786,2.799,2.811,2.823,2.835,2.846,2.857,2.866,
                    2.877,2.887,2.896,2.905,2.914,2.923,2.931,2.940,2.948,2.956,
                    2.943,2.971,2.978,2.986,2.992,3.000,3.006,3.013,3.019,3.025,
                    3.032,3.037,3.044,3.049,3.055,3.061,3.066,3.071,3.076,3.082,
                    3.087,3.092,3.098,3.102,3.107,3.111,3.117,3.121,3.125,3.130,
                    3.134,3.139,3.143,3.147,3.151,3.155,3.160,3.163,3.167,3.171,
                    3.174,3.179,3.182,3.186,3.189,3.193,3.196,3.201,3.204,3.207 };


// 排序法则,其中:< 升序    >降序
bool comparison(data_sort a,data_sort b)
{
    return a.data < b.data ;
}

/**
 * @brief My_Grubbs 格拉布斯剔除法
 * @param data      待处理数据
 * @return
 */
bool My_Grubbs_(vector<data_sort> &data)
{
    sort(data.begin(), data.end(), comparison);
    // 计算平均值
    double data_sum = 0;
    for(int i=0; i<data.size(); i++)
    {
        data_sum += data.at(i).data;
    }
    double data_ave = data_sum/data.size(); // 平均值

    // 计算标准差
    data_sum = 0;
    for(int i=0; i<data.size(); i++)
    {
        data_sum += pow((data.at(i).data - data_ave), 2);
    }
    double data_s = sqrt(data_sum/(data.size() - 1));                                   // 标准差

    if(abs(data_ave - data.at(0).data) > abs(data.at(data.size()-1).data - data_ave))   // 当最小值与均值大于最大值与均值
    {
        if(abs(data.at(0).data - data_ave)/data_s > table[3])                           // 满足Gn大于Gp(n)时,为异常值,剔除最小值
        {
            data.erase(data.begin());       // 剔除最小值
            My_Grubbs_(data);               // 进行递归处理
        }
        else                                // 条件满足,可以结束
        {
            return true;
        }
    }
    else if(abs(data_ave - data.at(0).data) < abs(data.at(data.size()-1).data - data_ave))  // 当最大值与均值大于最小值与均值
    {
        if(abs(data.at(data.size()-1).data - data_ave)/data_s > table[data.size()-1])   // 满足Gn大于Gp(n)时,为异常值,剔除最大值
        {
            data.erase(data.begin()+data.size()-1);         // 剔除最大值
            My_Grubbs_(data);                               // 进行递归处理
        }
        else                                                // 条件满足,可以结束
        {
            return true;
        }
    }
    else    // 当最大值与均值等于最小值与均值
    {
        if(abs(data.at(0).data - data_ave)/data_s > table[3])   // 满足Gn大于Gp(n)时,为异常值,剔除最大值和最小值
        {
            data.erase(data.begin());                           // 剔除最小值
            data.erase(data.begin() + data.size()-1);           // 剔除最大值
            My_Grubbs_(data);                                   // 进行递归处理
        }
        else                                                // 条件满足,可以结束
        {
            return true;
        }
    }

    return true;
}

bool My_Grubbs(vector<float> &data_ori)
{
    vector<data_sort> data;
    for(int i=0; i<data_ori.size(); i++)
    {
        data_sort data_temp;
        data_temp.data = data_ori.at(i);
        data_temp.id = i;
        data.push_back(data_temp);
    }

    My_Grubbs_(data);

    data_ori.clear();
    for(int i=0; i<data.size(); i++)
    {
        data_ori.push_back(data.at(i).data);
    }

    if(!data.empty())
    {
        data.clear();
        vector<data_sort> tmp;
        data.swap(tmp);		// 进行交换
    }

    return true;
}

Ransac:随机抽样迭代判断内点与外点。

/**
 * @brief My_Ransac     随机抽样一致性滤波算法
 * @param data_ori      待滤波数据,最终滤波后数据
 * @param sigma         距离阈值
 * @param iters         迭代次数
 * @param P             外点占比比率
 * @return
 */
bool My_Ransac(vector<float> &data_ori, double sigma, int iters, double P)
{
    double best_k, best_b, pretotal = 0;
    vector<bool> data_reslut, data_reslut_temp;

    // 数据迁移
    vector<float> data;
    for(int i=0; i<data_ori.size(); i++)
    {
        data.push_back(data_ori.at(i));
        data_reslut.push_back(false);
        data_reslut_temp.push_back(false);
    }


    for(int N=0; N<iters; N++)
    {
        // 随机计算两点斜率及截距
        int dot_ind1 = rand() % (data.size()-1);
        int dot_ind2 = rand() % (data.size()-1);

        while(dot_ind1 == dot_ind2)
        {
            dot_ind2 = rand() % (data.size()-1);
        }

        double k = (data.at(dot_ind1) - data.at(dot_ind2))/(dot_ind1 - dot_ind2);
        double b = data.at(dot_ind1) - k*dot_ind1;

        // 计算内外点
        int total_inlier = 0;
        for(int i=0; i<data.size(); i++)
        {
            double reslut_temp = k*i + b;
            if(abs(reslut_temp - data.at(i)) < sigma)           // 判断是否为内点
            {
                data_reslut_temp.at(i) = true;
                total_inlier++;
            }
            else
            {
                data_reslut_temp.at(i) = false;
            }
        }

        // 更新迭代次数
        if(total_inlier > pretotal)
        {
            iters = log(1.0 - P)/log(1.0-pow(1.0 - double(double(total_inlier)/double(data.size())), 2));
            pretotal = total_inlier;
//            best_k= k;
//            best_b = b;

            for(int i=0; i<data.size(); i++)
            {
                data_reslut.at(i) = data_reslut_temp.at(i);
            }
        }
    }

    // 滤波数据更新
    data_ori.clear();
    for(int i=0; i<data.size(); i++)
    {
        if(data_reslut.at(i) == true)
        {
            data_ori.push_back(data.at((i)));
        }
    }

    if(!data.empty())
    {
        data.clear();
        vector<float> tmp;
        data.swap(tmp);		// 进行交换
    }

    if(!data_reslut.empty())
    {
        data_reslut.clear();
        vector<bool> tmp;
        data_reslut.swap(tmp);		// 进行交换
    }

    if(!data_reslut_temp.empty())
    {
        data_reslut_temp.clear();
        vector<bool> tmp;
        data_reslut_temp.swap(tmp);		// 进行交换
    }

    return true;
}

使用中可以根据实际需求,选择相应的算法,或者直接尝试不同滤波方案的效果。

你可能感兴趣的:(算法,c++,开发语言)