在MATLAB中,当我在具有对象的二进制图像上应用bwlabel
时,我得到一个地图,用于标识哪些像素属于哪个对象。但是,某些对象彼此接近,应该属于同一个对象。 (例如标记为1,2,3的三个对象,但它们应合并为一个。)我可以以某种方式合并这些区域吗?
答案 0 :(得分:1)
我有一些代码可以帮助您入门。这是从MATLAB中获取一个充满文本的样本图像。之后,我所做的是从文本中提取出每个字母的边界框。一旦我这样做,我提取了它们的质心位置,以及与边界框内每个对象相对应的像素。我使用这两个属性来帮助我获得粗略的聚类算法。
以下是我写的算法的步骤:
这是我写的算法:
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');
这是我得到的图像:
变量clusterMapColour
将说明哪些对象属于彩色编码地图中的哪个群集。您真正关注的是map
变量。这与bwlabel
的输出非常相似,只是具有相同标签k
的对象属于群集k
。您必须使用distThreshold
变量来获取所需的结果。我选择30
作为一种随意的东西,并开始使用。这意味着质心30
像素半径的任何内容都被归类为与该质心相同的成员资格。此外,我们会跟踪已经访问过的对象,以便在我们在图像中移动时不再重新分类。