如何在MATLAB中将bwlabel合并到附近区域?

时间:2014-06-01 18:02:41

标签: image matlab image-processing

在MATLAB中,当我在具有对象的二进制图像上应用bwlabel时,我得到一个地图,用于标识哪些像素属于哪个对象。但是,某些对象彼此接近,应该属于同一个对象。 (例如标记为1,2,3的三个对象,但它们应合并为一个。)我可以以某种方式合并这些区域吗?

1 个答案:

答案 0 :(得分:1)

我有一些代码可以帮助您入门。这是从MATLAB中获取一个充满文本的样本图像。之后,我所做的是从文本中提取出每个字母的边界框。一旦我这样做,我提取了它们的质心位置,以及与边界框内每个对象相对应的像素。我使用这两个属性来帮助我获得粗略的聚类算法。

以下是我写的算法的步骤:

  1. 读入图像并提取每个对象的每个对象的质心和像素位置
  2. 创建一个数组,跟踪我们需要访问的对象
  3. 虽然我们需要访问至少一个对象:
    • 查找具有此条件的任何对象
    • 将此对象分配给其成员资格仅为此对象的新群集
    • 找到此对象的质心与其他对象的质心之间的距离
    • 如果有欧几里德距离低于某个值的质心,则它与我们在开头声明的对象属于同一个集群。将所有这些对象分配到同一个群集。
  4. 重复步骤#3,直到我们不再需要访问的群集为止。
  5. 这是我写的算法:

    clear all;
    close all;
    
    %//Read in text and extract properties
    BW = imread('text.png');
    s  = regionprops(BW, 'Centroid', 'PixelList');
    
    %//Create an array that tells us whether or not we have visited this
    %//centroid
    centroidVisited = false(length(s),1);
    
    %//Create an array that tells us which object belongs to what cluster
    membershipList = zeros(length(s),1);
    
    %//List of all centroids for each object
    centroidList = reshape([s.Centroid], 2, length(s)).';
    
    %//Initialize cluster count
    clusterNumber = 1;
    
    %//Threshold to figure out what is near
    distThreshold = 30;
    
    %//Map that gives us which pixel belongs to which cluster
    map = zeros(size(BW));
    
    %//If there are any objects we haven't visited...
    while (any(centroidVisited == false))
    
        %//Find one object
        ind = find(centroidVisited == false, 1);
    
        %//Extract its centroid
        cent = s(ind).Centroid;
    
        %//Grab pixels where this object is valid
        pixelLocs = s(ind).PixelList;
    
        %//Find Euclidean distance squared between this centroid to all the
        %//other centroids
        distCentroids = sum(bsxfun(@minus, cent, centroidList).^2, 2);
    
        %//Find those locations that are lower than the centroid
        %//Also ensure that we filter out those locations that we have already visited
        belowThresh = find(distCentroids < distThreshold*distThreshold & ...
                           centroidVisited == false);
    
        %//Mark them as visited
        centroidVisited(belowThresh) = true;
    
        %//Assign their membership number
        membershipList(belowThresh) = clusterNumber;
    
        %//For each object that belongs to this cluster, mark them with this
        %//membership number
        for k = 1 : length(belowThresh)
            placesToMark = s(belowThresh(k)).PixelList;
            map(sub2ind(size(BW), placesToMark(:,2), placesToMark(:,1))) = ...
               clusterNumber;
        end
    
        %//For the next cluster 
       clusterNumber = clusterNumber + 1;    
    end
    
    %//Create a colour map that is the same size as the number of clusters
    colourMap = jet(clusterNumber);
    
    %//This colour map will contain what letters belong to what cluster (colour
    %//coded)
    colourMapRed = colourMap(:,1);
    colourMapGreen = colourMap(:,2);
    colourMapBlue = colourMap(:,3);
    
    mapColumn = map(:) + 1;
    redPlane = colourMapRed(mapColumn);
    greenPlane = colourMapGreen(mapColumn);
    bluePlane = colourMapBlue(mapColumn);
    
    redPlane = reshape(redPlane, size(BW,1), size(BW,2));
    greenPlane = reshape(greenPlane, size(BW,1), size(BW,2));
    bluePlane = reshape(bluePlane, size(BW,1), size(BW,2));
    
    clusterMapColour = cat(3,redPlane, greenPlane, bluePlane);
    
    figure;
    subplot(1,2,1);
    imshow(BW);
    title('Original Image');
    subplot(1,2,2);
    imshow(clusterMapColour);
    title('Clustered Image');
    

    这是我得到的图像:

    enter image description here

    变量clusterMapColour将说明哪些对象属于彩色编码地图中的哪个群集。您真正关注的是map变量。这与bwlabel的输出非常相似,只是具有相同标签k的对象属于群集k。您必须使用distThreshold变量来获取所需的结果。我选择30作为一种随意的东西,并开始使用。这意味着质心30像素半径的任何内容都被归类为与该质心相同的成员资格。此外,我们会跟踪已经访问过的对象,以便在我们在图像中移动时不再重新分类。

    祝你好运!