Matlab 减少像素的局部邻域

Matlab 减少像素的局部邻域,matlab,image-processing,computer-vision,Matlab,Image Processing,Computer Vision,我最近遇到了一个我似乎无法解决的问题。我有一张经过处理的图像,它包含了许多像素,这些像素以小的“局部”组分布在整个图像上。我希望找到每组的“中心”,并在输出图像中放置一个像素作为每组的代表。分组可以是一个紧密的组,它们之间没有像素零间距,也可以是一个较小的扩展组,它们之间只有几个(小于4~5像素)。我的第一个想法是使用一些沿着形态侵蚀线的东西,但这不能解释稍微分散的像素组的情况。我只是想知道是否有人能给我指出正确的方向。以下是我想做的一个例子: 左侧图像显示输入(大黑点表示一组像素,它们之间没有

我最近遇到了一个我似乎无法解决的问题。我有一张经过处理的图像,它包含了许多像素,这些像素以小的“局部”组分布在整个图像上。我希望找到每组的“中心”,并在输出图像中放置一个像素作为每组的代表。分组可以是一个紧密的组,它们之间没有像素零间距,也可以是一个较小的扩展组,它们之间只有几个(小于4~5像素)。我的第一个想法是使用一些沿着形态侵蚀线的东西,但这不能解释稍微分散的像素组的情况。我只是想知道是否有人能给我指出正确的方向。以下是我想做的一个例子: 左侧图像显示输入(大黑点表示一组像素,它们之间没有零),右侧图像是我想要的输出或处理图像类型的示例。最后,我使用MATLAB,可以假设输入图像是一个二值图像(无论黑色是1还是0,逻辑都应该是相同的)

非常感谢你的帮助


编辑:感谢大家的意见-我将在第二天左右尝试不同的解决方案,我将尝试回复我所做的每个人。非常感谢你们的富有洞察力的投入,非常感谢。

在这种情况下,您可以使用区域增长方法,首先连接clstered像素,然后使用腐蚀。如果你知道集群之间的距离比集群本身大的话,那就行了。可能使用重心来确定区域增长后每个斑点的中间。

在这种情况下,您可以使用区域增长方法首先连接clstered像素,然后使用腐蚀。如果你知道集群之间的距离比集群本身大的话,那就行了。也许可以使用重心来确定区域生长后每个斑点的中间位置。

我推荐一种方法,包括形态学闭合,然后进行连接成分分析。请注意,我已将问题倒置,因此“好点”值较高,“坏背景”值为黑色。这更符合形态学操作的预期定义

path = 'yourimage.png'
space = 5; % you can change this to make it accept bigger spacings

input = imcomplement(rgb2gray(imread(path))) > 0;
input = imclose(input, strel('disk', space));
[labels, num] = bwlabel(input, 8);
output = logical(zeros(size(input)));
for i = 1:num
   [r, c] = find(labels==i); 
   x = round(mean(c))
   y = round(mean(r))
   output(y,x) = 1;
end

imshow(output)
结果如下所示:


在我看来,这就是你要找的

我推荐一种方法,先进行形态闭合,然后进行连接成分分析。请注意,我已将问题倒置,因此“好点”值较高,“坏背景”值为黑色。这更符合形态学操作的预期定义

path = 'yourimage.png'
space = 5; % you can change this to make it accept bigger spacings

input = imcomplement(rgb2gray(imread(path))) > 0;
input = imclose(input, strel('disk', space));
[labels, num] = bwlabel(input, 8);
output = logical(zeros(size(input)));
for i = 1:num
   [r, c] = find(labels==i); 
   x = round(mean(c))
   y = round(mean(r))
   output(y,x) = 1;
end

imshow(output)
结果如下所示:


在我看来,这就是你要找的

您描述的问题通常称为。根据您的数据集和分析约束,这可能非常困难。然而,在您的情况下,它很简单,因为您有一个硬阈值(5像素)要使用

Aardvarkk已经提出了一个很好的解决方案,但它并没有真正演示集群的过程。这是一种非常简单的方法,可以对数据进行聚类,得到大致相同的结果

  • 计算点之间的成对距离。对于N个点,这将生成一个NxN矩阵
  • 阈值矩阵
  • 遍历矩阵的行
  • 每个迭代将如下所示:

    • 如果
      i
      已群集,请继续
    • 如果
      i
      不在集群中,则创建一个新集群并将
      i
      分配给它
    • 找到靠近
      i
      的所有其他点(行
      i
      中等于1的列)
    • 检查这些点是否已在群集中
    • 如果是,则将
      i
      i
      附近的所有点设置为最小群集id
    • 如果未设置
      i
      ,且靠近
      i
      的所有点都设置为
      i的
    下面是我快速想出的一个例子:

    %Generate random points
    nPts = 300;
    clustId = zeros(nPts,1);
    clusterCount = 0;
    x = randi(3, [1, nPts])*10+ randn(1, nPts);
    y = randi(3, [1, nPts])*10 + randn(1, nPts);
    
    %Compute the distance matrix  from http://goo.gl/8mAoC
    dist = distance([x;y], [x;y]);
    
    maxDist = 5;
    binDist = dist <= maxDist;
    
    
    for i = 1:nPts
        % if this point is already clustered skip it
        if clustId(i) ~= 0
            continue;
        end
    
        %if the current point isn't in a cluster, create a new cluster and add
        %the point to that cluster
        if clustId(i) == 0
            clusterCount = clusterCount+1;
            clustId(i) = clusterCount;
            fprintf('New point, creating cluster:%d\n', clusterCount);
        end
    
        % get the indices of the points that collide with the i
        idx = binDist(:,i);
    
        % check to see if idx contains points that already belong to another clustered
        % if it doesn't collisionIdx will be equal to i
        collisionIdx = idx & clustId>0;
    
        %get the smallest cluster from collisionIdx
        mergeClustId = min(clustId(collisionIdx));
    
        %assing all the original points to that cluster
        clustId(idx) = mergeClustId;
    end
    
    然后将结果绘制为:

    figure; 
    plot(cx,cy,'c.', 'markersize', 50); hold on;
    plot(x,y,'.');
    

    您描述的问题通常称为。根据您的数据集和分析约束,这可能非常困难。然而,在您的情况下,它很简单,因为您有一个硬阈值(5像素)要使用

    Aardvarkk已经提出了一个很好的解决方案,但它并没有真正演示集群的过程。这是一种非常简单的方法,可以对数据进行聚类,得到大致相同的结果

  • 计算点之间的成对距离。对于N个点,这将生成一个NxN矩阵
  • 阈值矩阵
  • 遍历矩阵的行
  • 每个迭代将如下所示:

    • 如果
      i
      已群集,请继续
    • 如果
      i
      不在集群中,则创建一个新集群并将
      i
      分配给它
    • 找到靠近
      i
      的所有其他点(行
      i
      中等于1的列)
    • 检查这些点是否已在群集中
    • 如果是,则将
      i
      i
      附近的所有点设置为最小群集id
    • 如果未设置
      i
      ,且靠近
      i
      的所有点都设置为
      i的
    下面是我快速想出的一个例子:

    %Generate random points
    nPts = 300;
    clustId = zeros(nPts,1);
    clusterCount = 0;
    x = randi(3, [1, nPts])*10+ randn(1, nPts);
    y = randi(3, [1, nPts])*10 + randn(1, nPts);
    
    %Compute the distance matrix  from http://goo.gl/8mAoC
    dist = distance([x;y], [x;y]);
    
    maxDist = 5;
    binDist = dist <= maxDist;
    
    
    for i = 1:nPts
        % if this point is already clustered skip it
        if clustId(i) ~= 0
            continue;
        end
    
        %if the current point isn't in a cluster, create a new cluster and add
        %the point to that cluster
        if clustId(i) == 0
            clusterCount = clusterCount+1;
            clustId(i) = clusterCount;
            fprintf('New point, creating cluster:%d\n', clusterCount);
        end
    
        % get the indices of the points that collide with the i
        idx = binDist(:,i);
    
        % check to see if idx contains points that already belong to another clustered
        % if it doesn't collisionIdx will be equal to i
        collisionIdx = idx & clustId>0;
    
        %get the smallest cluster from collisionIdx
        mergeClustId = min(clustId(collisionIdx));
    
        %assing all the original points to that cluster
        clustId(idx) = mergeClustId;
    end
    
    然后将结果绘制为:

    figure; 
    plot(cx,cy,'c.', 'markersize', 50); hold on;
    plot(x,y,'.');
    

    正如斯莱顿所指出的,这是一个集群问题

    由于集群的分离非常清楚,因此可以使用简单的基于图形的方法。如果您可以访问图形算法库(例如,存在许多绑定),那么以下方法应该非常简单:

  • 用边权重作为距离,构建点的完整图形
  • 计算最小生成tr