Matlab: Desenhe centróides
-
27-09-2019 - |
Pergunta
Minha pergunta principal recebe um recurso Centroid, como posso desenhá -lo no Matlab?
Em mais detalhes, eu tenho um NxNx3
imagem (uma imagem RGB) da qual tomo 4x4
bloqueia e calcule um 6
Vector de recurso dimensional para cada bloco. Eu guardo esses vetores de recursos em um Mx6
matriz em que eu corro kmeans
funcionar e obter os centróides em um kx6
Matrix, onde k
é o número de grupos e 6
é o número de recursos para cada bloco.
Como posso desenhar esses clusters centrais na minha imagem para visualizar se o algoritmo está executando a maneira como eu gostaria de realizar? Ou, se alguém tiver outra maneira/sugestão sobre como eu posso visualizar os centróides na minha imagem, eu agradeço muito.
Solução
Aqui está uma maneira de visualizar os clusters:
Como você descreveu, primeiro extrai os blocos, calculo o vetor de recurso para cada um e cluster essa matriz.
Em seguida, podemos visualizar os clusters atribuídos a cada bloco. Observe que estou assumindo que os blocos 4x4 são distintos, isso é importante para que possamos mapear os blocos para o local deles de volta na imagem original.
Por fim, para exibir os centróides do cluster na imagem, simplesmente encontro o bloco mais próximo de cada cluster e exibi -lo como um representante desse cluster.
Aqui está um exemplo completo para mostrar a idéia acima (no seu caso, você deseja substituir a função que calcula os recursos de cada bloco por sua própria implementação; estou simplesmente tomando o min/max/média/mediana/q1/Q3 como Meu vetor de recurso para cada bloco 4x4):
%# params
NUM_CLUSTERS = 3;
BLOCK_SIZE = 4;
featureFunc = @(X) [min(X); max(X); mean(X); prctile(X, [25 50 75])];
%# read image
I = imread('peppers.png');
I = double( rgb2gray(I) );
%# extract blocks as column
J = im2col(I, [BLOCK_SIZE BLOCK_SIZE], 'distinct'); %# 16-by-NumBlocks
%# compute features for each block
JJ = featureFunc(J)'; %'# NumBlocks-by-6
%# cluster blocks according to the features extracted
[clustIDX, ~, ~, Dist] = kmeans(JJ, NUM_CLUSTERS);
%# display the cluster index assigned for each block as an image
cc = reshape(clustIDX, ceil(size(I)/BLOCK_SIZE));
RGB = label2rgb(cc);
imshow(RGB), hold on
%# find and display the closest block to each cluster
[~,idx] = min(Dist);
[r c] = ind2sub(ceil(size(I)/BLOCK_SIZE), idx);
for i=1:NUM_CLUSTERS
text(c(i)+2, r(i), num2str(i), 'fontsize',20)
end
plot(c, r, 'k.', 'markersize',30)
legend('Centroids')
Outras dicas
Os centróides não correspondem às coordenadas na imagem, mas para coordenadas no espaço de recursos. Há duas maneiras pelas quais você pode testar o desempenho do Kmeans. Para os dois lados, você deseja associar os pontos ao seu cluster mais próximo. Você obtém essas informações da primeira saída de Kmeans.
(1) Você pode visualizar o resultado do cluster, reduzindo o espaço 6-dimensional para o espaço 2 ou tridimensional e, em seguida, plotando as coordenadas classificadas de maneira diferente em cores diferentes.
Supondo que os vetores de recurso sejam coletados em uma matriz chamada featureArray
, e que você pediu nClusters
Clusters, você faria o enredo o seguinte usando MDSCALE Para transformar os dados em, digamos, 3D Space:
%# kmeans clustering
[idx,centroids6D] = kmeans(featureArray,nClusters);
%# find the dissimilarity between features in the array for mdscale.
%# Add the cluster centroids to the points, so that they get transformed by mdscale as well.
%# I assume that you use Euclidean distance.
dissimilarities = pdist([featureArray;centroids6D]);
%# transform onto 3D space
transformedCoords = mdscale(dissimilarities,3);
%# create colormap with nClusters colors
cmap = hsv(nClusters);
%# loop to plot
figure
hold on,
for c = 1:nClusters
%# plot the coordinates
currentIdx = find(idx==c);
plot3(transformedCoords(currentIdx,1),transformedCoords(currentIdx,2),...
transformedCoords(currentIdx,3),'.','Color',cmap(c,:));
%# plot the cluster centroid with a black-edged square
plot3(transformedCoords(1:end-nClusters+c,1),transformedCoords(1:end-nClusters+c,2),...
transformedCoords(1:end-nClusters+c,3),'s','MarkerFaceColor',cmap(c,:),...
MarkerEdgeColor','k');
end
(2) Você pode, alternativamente, criar uma imagem pseudo-cor que mostra qual parte da imagem pertence a qual cluster
Supondo que você tenha nRows
por nCols
Blocks, você escreve
%# kmeans clustering
[idx,centroids6D] = kmeans(featureArray,nClusters);
%# create image
img = reshape(idx,nRows,nCols);
%# create colormap
cmap = hsv(nClusters);
%# show the image and color according to clusters
figure
imshow(img,[])
colormap(cmap)