DBSCAN C语言代码的实现(转载)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

void normalization_points(float point[][3], int rows)
{
//聚类前对数据做最大最小值归一化 保证每个维度量纲一致
// points – 原始数据点云
// rows – 传入参数的行数
// 聚类 只关注[x, y, v]
//归一化最值范围
float x_min = -20; //单位 m
float x_max = 20;
float y_min = 0;
float y_max = 50;
float v_max = 20; //单位 m/s
for (int i=0; i<rows; i++)
{
point[i][0] = (point[i][0] - x_min) / (x_max - x_min);
point[i][1] = (point[i][1] - y_min) / (y_max - y_min);
point[i][2] = fabsf(point[i][2]/ v_max);
}
}

float cal_distance(float point[][3], int firstPoint, int secondPoint)
{
float temp = sqrt( pow((double)(point[firstPoint][0] - point[secondPoint][0]), 2) + pow((double)(point[firstPoint][1] - point[secondPoint][1]), 2) + pow((double)(point[firstPoint][2] - point[secondPoint][2]), 2));
return temp;
}
void dbscan_cluster(float point[][3], int point_num, int MinPts, float neighborhood)
{
//预分配内存
int clusterIndex = (int)malloc(sizeof(int) * point_num); //聚类蔟标签
int dataType = (int)malloc(sizeof(int) * point_num); //区分是否为核心点
int visited_data = (int)malloc(sizeof(int) * point_num); //访问标志,访问过的为1,未访问的为0
memset(clusterIndex, 0, sizeof(int) * point_num);
memset(dataType, 0, sizeof(int) * point_num);
memset(visited_data, 0, sizeof(int) * point_num);

/* 求核心点 */
for(int i = 0; i<point_num; i++)
{
    int inter_point_num = 0;
    for(int j = 0; j<point_num; j++)
    {
        float distance =  cal_distance(point, i, j);
        if(distance <= neighborhood)
        {
            inter_point_num++;
        }
    }
    if(inter_point_num >=MinPts) //点数大于MinPts 为核心点
    {
        dataType[i] = 2; //核心点的标签为2
    }
}
/* 由核心点依次找密度可达点 */
int cluster_num = 0;
for(int i=0; i<point_num; i++)
{
    if((dataType[i]==2) && (!visited_data[i]))//若为核心点且还未分配类别,则由核心点查找密度可达点
    {
        visited_data[1] = 0;//
        int *record_single_cluster = (int*)malloc(sizeof(int) * point_num); //存储可达点索引
        int length = 0;
        memset(record_single_cluster, 0, sizeof(int) * point_num);
        //遍历查找密度可达点
        for(int j=0; j<point_num; j++)
        {
            if(!visited_data[j])
            {
                float temp = cal_distance(point, i, j);
                if(temp < neighborhood)
                {
                   record_single_cluster[length] = j;//记录当前序号
                   length++;
                }
            }
        }
        //若length > minPts,存为一个类别
        if(length > MinPts)
        {
            cluster_num++;//类别+1
            for(int j=0; j<length; j++)
            {
                visited_data[record_single_cluster[j]] = 1;
                clusterIndex[record_single_cluster[j]] = cluster_num;
            }
        }
        free(record_single_cluster);
        record_single_cluster = NULL;
    }
}

for(int i=0; i<point_num; i++)
{
    printf("%d\n", clusterIndex[i]);
}
/*  聚类完毕 */
/* cluster_num为类别总数,clusterIndex存储的为每个点的聚类类别,0为噪声 */

free(clusterIndex);
clusterIndex = NULL;
free(dataType);
dataType = NULL;
free(visited_data);
visited_data = NULL;

}

int main()
{
float point[13][3] = { {1,1,1},{1.1,1.1,1.1},{1,1.2,1.1},{15,15.1,18.1},{15.2,15.5,17.9},{1.3,1.1,1},{1.01,1.02,1.03},{5,5,5},{10.1,9.1,11.1},{5.01,5.02,5.03},{5.02,5.05,5.01},{5.02,5.01,5.05},{10,9,11}};
int point_num = 13;

normalization_points(point, point_num);
int MinPts = 3;
float neighborhood = 0.1;
dbscan_cluster(point, point_num, MinPts, neighborhood);
return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值