Advertisement

DDMA信号处理以及数据处理的流程---聚类

阅读量:

你好呀!很高兴见到你!我是Xiaojie,请允许我邀请大家深入探讨毫米波雷达技术。作为一名专业的研究者与教育工作者,在本次分享中我将带领大家一起学习毫米波雷达相关知识,并详细阐述这些关键环节的处理流程。我们将会从目标生成在内的重要内容开始讨论,并系统性地探讨包括信号仿真在内的重要内容。此外,在这一系列文章中我们将涵盖以下核心模块:目标生成、信号仿真、测距与测速等核心技术环节,并结合实际案例进行深入分析与讨论。预计共有七到八篇文章组成这个系列,请持续关注后续更新内容!

最终效果如下:

整体文件的目录树如下:

从这篇开始转入数据处理部分。本文着重讨论聚类技术及其应用情况。完成雷达信号处理后,则会生成目标点云信息,并包含距离参数、速度指标以及角度数据等关键参数。

dbscan聚类

名称为DBSCAN的数据挖掘算法即为Density-Based Spatial Clustering of Application with Noise(DBSCAN),其属于一种基于数据密度的空间聚类方法。

密度聚类算法主要假设类别是由样本之间的分布紧密程度所决定的。在同一个类别内部的所有样本之间具有高度相关性,在这种情况下,则会将这些高度相关的样本分组到同一类别中,并由此形成一个有意义的聚类结构。

核心思想:DBSCAN的核心思想是以样本点密度为基础实现聚类目标的方式,并通过在样本空间中识别密集区域来完成簇划分的过程。

算法主要参数由两部分组成:一是邻域范围d;二是最低样本数n_{\text{min}}。只有在数据集中某一点x其局部区域内的样本数量s(x)至少达到n_{\text{min}}时才能被认定为核心数据点

在DBSCAN算法中,空间中的数据样本被划分为三个互斥类别:核心对象、边缘对象和噪音对象。其中,核心对象被定义为在一定范围内包含足够数量的数据样本的对象;边缘对象则位于这些核心对象的周围区域,并不满足成为核心对象的标准;最后一种类型是噪音样本或异常值,在其所在区域内不具备足够的密度特征。

数据点之间的关系:在DBSCAN算法中,默认将数据点之间的关系划分为直接密度联系、间接密度联系以及基于连通性的密度联系三种类型。这些关系描述了如何从核心数据点延伸至整个数据集中的簇结构。

此处表述较为正式;实际上网上通常会有大量对dbscan聚类算法的解释;因此无需在此进一步阐述。

此处表述较为正式;实际上网上通常会有大量对dbscan聚类算法的解释;因此无需在此进一步阐述。

代码仿真

clusterProcess.m文件

该文件负责聚类核心功能的实现,并执行该算法的计算任务。该系统完成数据特征的统计分析,并对数据集进行分组整合过程处理。

代码如下:

复制代码
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %%点云处理模块
    %%1. dbscan聚类
    %%2. 计算聚类信息
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function [parameter,pointList] = clusterProcess(parameter,pointList,pointNums)
    %% dbscan聚类
    [pointList,clusterNums] = dbscanCore(parameter.clusterPara,pointList,pointNums);
    %% 计算聚类信息
    parameter = calClusterMsg(parameter,pointList,pointNums,clusterNums);
    %% 聚类合并
    if parameter.frameCount ~= 1 %后面进行聚类合并
        parameter = clusterMergeCluster(parameter);
    else %第一帧聚类直接赋值
        parameter = clusterEqualNewCluster(parameter);
    end
    end
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

dbscanCore.m文件

dbscanCore.m文件是核心聚类函数,在该文件中使用聚类算法将点云数据被分类为多个类别

复制代码
    %% dbscan聚类核心函数
    function [pointList,clusterNums] = dbscanCore(clusterPara,pointList,pointNums)
    
    [pointDistance] = calPointEuclideanDistance(pointList,pointNums); %计算点云的距离速度角度欧式距离
    clusterNums = 0; %聚类数目初始化
    IDX=zeros(pointNums,1);
    pointIsVisited = zeros(pointNums,1); %初始化所有点云都未被初始化
    
    for pointIdx = 1:1:pointNums %循环所有点
    
        if ~pointIsVisited(pointIdx) %当前点没被访问过
            
            pointIsVisited(pointIdx) = 1; %标记当前点被访问过
            neighbor = getPointNeighbor(pointDistance,pointIdx,clusterPara); %获取领域点数
            neighborNums = numel(neighbor); %领域点数
            if neighborNums < clusterPara.minPoints %领域点数小于阈值
            else %领域点数大于阈值
                clusterNums = clusterNums + 1; %聚类数目增加
                expandCluster(pointIdx,neighbor,clusterNums); %根据当前点访问领域点扩充
            end
        end
    end
    
    function expandCluster(pointIdx,neighbor,clusterNums)
        IDX(pointIdx)=clusterNums; %标记当前点云属于几号聚类
        pointList(pointIdx).clusterId = clusterNums; %标记当前点云属于几号聚类
        count = 1; %计数器
        while true
            
            pointIdxTmp = neighbor(count); %获取领域中的其他点云ID
            if ~pointIsVisited(pointIdxTmp) %该点云没有被访问过
                pointIsVisited(pointIdxTmp) = 1; %标记其被访问过
                neighbor2 = getPointNeighbor(pointDistance,pointIdxTmp,clusterPara); %获取pointIdxTmp的领域点数
                neighbor2Nums = numel(neighbor2); %领域点数
                if neighbor2Nums >= clusterPara.minPoints %领域点数大于阈值
                    neighbor = [neighbor,neighbor2]; %扩充neighbor
                end
            end
            if IDX(pointIdxTmp)==0 %当前点属于空闲点
                IDX(pointIdxTmp)=clusterNums; %标记为几号聚类
                pointList(pointIdxTmp).clusterId = clusterNums; %标记为几号聚类
            end
            count = count + 1; %计数器累加
            
            if count > numel(neighbor) %循环完毕所有邻域中的点云
                break;
            end
        end
    end
    end
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

calPointEuclideanDistance.m文件

calPointEuclideanDistance.m文件是计算点云与点云之间的欧式距离

复制代码
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %%计算距离、速度、角度的欧式距离
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function [pointDistance] = calPointEuclideanDistance(pointList,pointNums)
    
    for pointIdxI = 1:1:pointNums
        for pointIdxJ = 1:1:pointNums
            %距离欧式距离
            pointDistance.rangeD(pointIdxI,pointIdxJ) = ...
                sqrt((abs(pointList(pointIdxI).range)-abs(pointList(pointIdxJ).range)).^2);
            %速度欧式距离
            pointDistance.speedD(pointIdxI,pointIdxJ) = ...
                sqrt((abs(pointList(pointIdxI).speed)-abs(pointList(pointIdxJ).speed)).^2);
            %角度欧式距离
            pointDistance.angleD(pointIdxI,pointIdxJ) = ...
                sqrt((abs(pointList(pointIdxI).angle)-abs(pointList(pointIdxJ).angle)).^2);
        end
    end
    
    end
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

getPointNeighbor.m文件

getPointNeighbor.m文件是获取当前点的邻域信息

复制代码
    %% 获取当前点的领域信息
    function neighbor = getPointNeighbor(pointDistance,currPointIdx,clusterPara)
    
    neighbor = [];
    pointRangeDistance = pointDistance.rangeD;[rangeRow,rangeCol] = size(pointRangeDistance);
    pointSpeedDistance = pointDistance.speedD;[speedRow,speedCol] = size(pointSpeedDistance);
    pointAngleDistance = pointDistance.angleD;[angleRow,angleCol] = size(pointAngleDistance);
    if (rangeCol == speedCol) && (rangeCol == angleCol) && (speedCol && angleCol)
        for colIdx = 1:1:rangeCol
            if pointRangeDistance(currPointIdx,colIdx) < clusterPara.rangeThreshold && ...
                pointSpeedDistance(currPointIdx,colIdx) < clusterPara.speedThreshold && ...
                pointAngleDistance(currPointIdx,colIdx) < clusterPara.angleThreshold
            
                neighbor = [neighbor, colIdx];
                
            end
        end
    end
    end
    
    
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

clusterMergeCluster.m

该M文件的功能是实现将新增的聚类与现有聚类进行合并。

该M文件的功能是实现将新增的聚类与现有聚类进行合并。

复制代码
    function parameter = clusterMergeCluster(parameter)
    
    distanceThresh = 6; %合并聚类的阈值
    %     clusterCurrNums = 0;
    for newClusterIdx = 1:1:parameter.clusterPara.newClusterCurrNums %下一帧形成聚类
    
        newLa = parameter.clusterPara.newClusterTarget(newClusterIdx).la;
        newLo = parameter.clusterPara.newClusterTarget(newClusterIdx).lo;
        newVLa = parameter.clusterPara.newClusterTarget(newClusterIdx).V_La;
        newVLo = parameter.clusterPara.newClusterTarget(newClusterIdx).V_Lo;
        maxDistance = 999; %默认最大距离
        updateClusterIdx = -1; %要更新的ID
        distance = -1; %默认距离
        for clusterIdx = 1:1:parameter.clusterPara.clusterCurrNums %已经存在的聚类
                la = parameter.clusterPara.clusterTarget(clusterIdx).la;
                lo = parameter.clusterPara.clusterTarget(clusterIdx).lo;
                vLa = parameter.clusterPara.clusterTarget(clusterIdx).V_La;
                vLo = parameter.clusterPara.clusterTarget(clusterIdx).V_Lo;
                distance = sqrt((abs(la) - abs(newLa)).^2 + (abs(lo) - abs(newLo)).^2 + ...
                    (abs(vLa) - abs(newVLa)).^2 + (abs(vLo) - abs(newVLo)).^2);
                if distance < maxDistance && distance < distanceThresh %取最小值
                    updateClusterIdx = clusterIdx;
    %                     distance = maxDistance;
                    maxDistance = distance;
                end
        end
        if updateClusterIdx == -1 %新建聚类
                clusterCurrNums = parameter.clusterPara.clusterCurrNums + 1; %TODO
                parameter.clusterPara.clusterTarget(clusterCurrNums) = ...
                    parameter.clusterPara.newClusterTarget(newClusterIdx); %聚类赋值
                parameter.clusterPara.newClusterTarget(clusterCurrNums).isMerge = 2;
        else  %以前存在的聚类
            isMerge = parameter.clusterPara.newClusterTarget(updateClusterIdx).isMerge; %获取合并标志
            if isMerge == 0 %表明聚类没有合并过
                count = parameter.clusterPara.clusterTarget(updateClusterIdx).count; %获取已经存在聚类的出现次数
                parameter.clusterPara.clusterTarget(updateClusterIdx) = ...
                    parameter.clusterPara.newClusterTarget(newClusterIdx); %聚类信息赋值
                parameter.clusterPara.clusterTarget(updateClusterIdx).count = ...
                    count + 1; %标记出现次数增加
                parameter.clusterPara.newClusterTarget(updateClusterIdx).isMerge = 1; %表明新建的聚和以前存在的聚类合并
            end
        end
    end
    parameter.clusterPara.clusterCurrNums = parameter.clusterPara.newClusterCurrNums; %聚类数目更新 TODO
    % 合并标志重新赋值为0
    for newClusterIdx = 1:1:parameter.clusterPara.newClusterCurrNums
        parameter.clusterPara.newClusterTarget(newClusterIdx).isMerge = 0;
    end
    end
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

calClusterMsg.m文件

calClusterMsg.m文件计算聚类结果的信息

复制代码
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %%计算聚类相关信息
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function parameter = calClusterMsg(parameter,pointList,pointNums,clusterNums)
    
    for clusterIdx = 1:1:clusterNums
       %% 初始信息初始化
        pointLa = 0; %点云纵距和
        pointLo = 0; %点云横距和
        pointVLa = 0; %点云纵向速度和
        pointVLo = 0; %点云横向速度和
        pointCount = 0; %点云总数
       %% 统计当前聚类所有点云的点云数、横距、纵距、纵向速度、横向速度的和
        for pointIdx = 1:1:pointNums 
            if pointList(pointIdx).clusterId == clusterIdx
                pointCount = pointCount + 1;
                pointLa = pointLa + pointList(pointIdx).la;
                pointLo = pointLo + pointList(pointIdx).lo;
                pointVLa = pointVLa + pointList(pointIdx).V_La;
                pointVLo = pointVLo + pointList(pointIdx).V_Lo;
            end
        end
       %% 信息赋值
        parameter.clusterPara.newClusterTarget(clusterIdx).pointNums = pointCount; %点云数赋值
        parameter.clusterPara.newClusterTarget(clusterIdx).count = 1; %聚类计数值每次都初始化为1
        parameter.clusterPara.newClusterTarget(clusterIdx).V_La = pointVLa / pointCount; %纵向速度平均
        parameter.clusterPara.newClusterTarget(clusterIdx).V_Lo = pointVLo / pointCount; %横向速度平均
        
        parameter.clusterPara.newClusterTarget(clusterIdx).la = pointLa / pointCount; %纵距平均
        parameter.clusterPara.newClusterTarget(clusterIdx).lo = pointLo / pointCount; %横距平均
       %% 聚类四个角度赋值
        parameter.clusterPara.newClusterTarget(clusterIdx).leftUPCornerLa = ...
            parameter.clusterPara.newClusterTarget(clusterIdx).la + 1.5;
        parameter.clusterPara.newClusterTarget(clusterIdx).leftUPCornerLo = ...
            parameter.clusterPara.newClusterTarget(clusterIdx).lo - 1.5;
        
        parameter.clusterPara.newClusterTarget(clusterIdx).rightUPCornerLa = ...
            parameter.clusterPara.newClusterTarget(clusterIdx).la + 1.5;
        parameter.clusterPara.newClusterTarget(clusterIdx).rightUPCornerLo = ...
            parameter.clusterPara.newClusterTarget(clusterIdx).lo + 1.5;
        
        parameter.clusterPara.newClusterTarget(clusterIdx).leftDownCornerLa = ...
            parameter.clusterPara.newClusterTarget(clusterIdx).la - 1.5;
        parameter.clusterPara.newClusterTarget(clusterIdx).leftDownCornerLo = ...
            parameter.clusterPara.newClusterTarget(clusterIdx).lo - 1.5;
    
        parameter.clusterPara.newClusterTarget(clusterIdx).rightDownCornerLa = ...
            parameter.clusterPara.newClusterTarget(clusterIdx).la - 1.5;
        parameter.clusterPara.newClusterTarget(clusterIdx).rightDownCornerLo = ...
            parameter.clusterPara.newClusterTarget(clusterIdx).lo + 1.5;
       %% 赋值给newClusterCurrNums
        parameter.clusterPara.newClusterCurrNums = clusterNums;
    
    end
    
    end
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

运行结果如下:

至此,本片文章就此结束了。

全部评论 (0)

还没有任何评论哟~