Algorithm 在散乱数据中寻找区域

Algorithm 在散乱数据中寻找区域,algorithm,matlab,Algorithm,Matlab,我在Nx3矩阵中有许多分散的数据集,下面是一个用scatter3绘制的简单示例(): 我的每个数据集都有任意数量的区域/blob;例如,上面的例子有4个 有没有人知道一种简单的方法,可以通过编程来查找这种数据形式中的区域数 我最初的想法是使用delaunay三角剖分,convexHull方法,但没有任何数据处理,这仍然只能找到整个绘图的外部体积,而不是每个区域 我的下一个想法是获取每个点的最近邻统计数据,询问它是否在另一个点的网格大小距离内,然后将其中的数据集中到单独的斑点/簇中 有没有一个我不

我在Nx3矩阵中有许多分散的数据集,下面是一个用
scatter3
绘制的简单示例(): 我的每个数据集都有任意数量的区域/blob;例如,上面的例子有4个

有没有人知道一种简单的方法,可以通过编程来查找这种数据形式中的区域数

我最初的想法是使用
delaunay三角剖分
convexHull
方法,但没有任何数据处理,这仍然只能找到整个绘图的外部体积,而不是每个区域

我的下一个想法是获取每个点的最近邻统计数据,询问它是否在另一个点的网格大小距离内,然后将其中的数据集中到单独的斑点/簇中


有没有一个我不知道的更高级别的Matlab函数可以帮助我,或者有没有人对如何从这样的数据中提取区域计数有更好的建议?

确定数据集中不同簇的数量是一个棘手的问题,可能比我们第一眼看到的要困难。事实上,像k-means这样的算法在很大程度上依赖于此。有一篇很好的文章,但是没有清晰简单的方法

其中提到的方法似乎比较容易实现,但计算成本可能较高。本质上,您可以尝试使用不同数量的集群,并选择方差增长不大且趋于平稳的集群


此外,集群的概念需要明确定义-如果放大任何一个blob显示出与图片中的角结构相似的结构会怎么样?

确定数据集中不同集群的数量是一个棘手的问题,可能比我们第一眼看到的要难。事实上,像k-means这样的算法在很大程度上依赖于此。有一篇很好的文章,但是没有清晰简单的方法

其中提到的方法似乎比较容易实现,但计算成本可能较高。本质上,您可以尝试使用不同数量的集群,并选择方差增长不大且趋于平稳的集群


此外,集群的概念需要明确定义-如果放大任何一个blob显示出与图片中的角结构相似的结构,该怎么办?

听起来您需要一个集群算法。幸运的是,MATLAB提供了许多现成的功能。有很多算法可供选择,听起来你需要一些事先不知道集群数量的算法,对吗

如果是这种情况,并且您的数据与您的示例一样“好”,我建议结合一种技术,按照建议正确选择“k”


当然还有其他选项,我建议您在MATLAB中学习更多关于集群选项的知识,这里有一个很好的例子供您阅读

听起来你需要一个聚类算法。幸运的是,MATLAB提供了许多现成的功能。有很多算法可供选择,听起来你需要一些事先不知道集群数量的算法,对吗

如果是这种情况,并且您的数据与您的示例一样“好”,我建议结合一种技术,按照建议正确选择“k”


当然还有其他选项,我建议您在MATLAB中学习更多关于集群选项的知识,这里有一个很好的例子供您阅读

我建议实施高斯混合模型的“轻”版本。 让每个点为一个立方体“投票”。在上面的示例中,以(-1.5,-1.5,0)为中心的所有点
每一个都会在正方形[-1,-2]x[-1,-2]x[0.2,-0.2]上加一个+1。最后,您可以分析投票矩阵中的峰值。

我建议实现高斯混合模型的“光”版本。 让每个点为一个立方体“投票”。在上面的示例中,以(-1.5,-1.5,0)为中心的所有点
每一个都会在正方形[-1,-2]x[-1,-2]x[0.2,-0.2]上加一个+1。最后,您可以分析投票矩阵中的峰值。

为了完整性起见,对于这个问题(我已经构建了)有一个比分层聚类更简单的答案;这提供了更好的结果,可以区分1个集群或2个集群(我无法用MarkV的建议解决这个问题)。这假设您的数据位于已知大小的常规网格上,并且您有未知数量的群集,这些群集之间至少间隔2*(网格大小):

%的想法如下:
%*我们有一个已知的网格大小dx。
%*随机点[也可以是极小值(1,:)]将位于
%如果列表中的任何其他值位于dx之外(具有一个维度
%变化),sqrt(2)*dx(二维变化)或sqrt(3)*dx(三维变化)
%尺寸不同)。
%*将这些对象链接在一起,直到找到所有对象,任意距离
%现在忽略集群的sqrt(3)*dx以外的部分。
%*将此群集放在一边,重复此操作,直到没有剩余最小值数据。
函数[blobs,clusterIdx]=findClusters(极小值,dx)
%问题设置
dx2=sqrt(2)*dx;
dx3=sqrt(3)*dx;
eqf=@(列表,dx,dx2,dx3)(abs(列表dx)<0.001;abs(列表dx2)<0.001;abs(列表dx3)<0.001);
notDoneClust=true;
notDoneMinima=true;
clusterIdx=零(大小(最小值,1),1);
点=最小值(1,:);
列表=最小值(2:结束,:);
blobs=0;
而不是多奈米玛
集群=nan(1,3);
而不是不信任
[~,dist]=knSearch(点,列表);%数据中每个点之间的所有距离
nnidx=eqf(距离,dx,dx2,dx3);%查找要指向的nn值的索引
群集=类别(1,群集,点,列表(nnidx,:);%将点添加到当前群集
点=列表(nnidx,:);%要检查的点现在是相对于初始点nn的所有值
列表=列表(~nnidx,:);%列表现在是不在该列表中的所有其他值
notDoneClust=~isempty(点);%如果有
% Idea is as follows: 
% * We have a known grid size, dx. 
% * A random point [may as well be minima(1,:)] will be in a cluster of 
%   values if any others in the list lie dx away (with one dimention 
%   varied), sqrt(2)*dx (two dimensions varied) or sqrt(3)*dx (three 
%   dimensions varied).
% * Chain these objects together until all are found, any with distances
%   beyond sqrt(3)*dx of the cluster are ignored for now.
% * Set this cluster aside, repeat until no minima data is left.

function [blobs, clusterIdx] = findClusters(minima,dx)
%problem setup
dx2 = sqrt(2)*dx;
dx3 = sqrt(3)*dx;
eqf = @(list,dx,dx2,dx3)(abs(list-dx) < 0.001 | abs(list-dx2) < 0.001 | abs(list-dx3) < 0.001);
notDoneClust = true;
notDoneMinima = true;

clusterIdx = zeros(size(minima,1),1);
point = minima(1,:);
list = minima(2:end,:);
blobs = 0;

while notDoneMinima
    cluster = nan(1,3);

    while notDoneClust
        [~, dist] = knnsearch(point,list); %All distances to each other point in data
        nnidx = eqf(dist,dx,dx2,dx3); %finds indexes of nn values to point

        cluster = cat(1,cluster,point,list(nnidx,:)); %add points to current cluster
        point = list(nnidx,:); %points to check are now all values that are nn to initial point
        list = list(~nnidx,:); %list is now all other values that are not in that list

        notDoneClust = ~isempty(point); %if there are no more points to check, all values of the cluster have been found
    end
    blobs = blobs+1;
    clusterIdx(ismemberf(minima,cluster(2:end,:),'rows')) = blobs;

    %reset points and list for a new cluster
    if ~isempty(list)
        if length(list)>1
            point = list(1,:);
            list = list(2:end,:);
            notDoneClust = true;
        else
            %point is a cluster of its own. Don't reset loops, add point in
            %as a cluster and exit (NOTE: I have yet to test this portion).
            blobs = blobs+1;
            clusterIdx(ismemberf(minima,point,'rows')) = blobs;
            notDoneMinima = false;
        end
    else
        notDoneMinima = false;
    end
end
end