用于图像压缩的K均值仅产生黑白结果

时间:2016-06-08 17:27:29

标签: algorithm matlab k-means

我正在做这个由Andrew NG做的关于使用k-means来减少图像颜色数量的练习。但问题是我的代码只给出了一个黑白图像:(。我已经检查了算法的每一步但它仍然没有给出正确的结果。请帮助我,非常感谢

以下是link of the exercise,此处是dataset。 在练习的链接中给出了正确的结果。这是我的黑白图像:

enter image description here

这是我的代码:

function [] = KMeans()

    Image = double(imread('bird_small.tiff'));
    [rows,cols, RGB] = size(Image);
    Points = reshape(Image,rows * cols, RGB);
    K = 16;
    Centroids = zeros(K,RGB);    
    s = RandStream('mt19937ar','Seed',0);
    % Initialization :
    % Pick out K random colours and make sure they are all different
    % from each other! This prevents the situation where two of the means
    % are assigned to the exact same colour, therefore we don't have to 
    % worry about division by zero in the E-step 
    % However, if K = 16 for example, and there are only 15 colours in the
    % image, then this while loop will never exit!!! This needs to be
    % addressed in the future :( 
    % TODO : Vectorize this part!
    done = false;
    while done == false
        RowIndex = randperm(s,rows);
        ColIndex = randperm(s,cols);
        RowIndex = RowIndex(1:K);
        ColIndex = ColIndex(1:K);
        for i = 1 : K
            for j = 1 : RGB
                Centroids(i,j) = Image(RowIndex(i),ColIndex(i),j);
            end
        end
        Centroids = sort(Centroids,2);
        Centroids = unique(Centroids,'rows'); 
        if size(Centroids,1) == K
            done = true;
        end
    end;
%     imshow(imread('bird_small.tiff'))
%    
%     for i = 1 : K
%         hold on;
%         plot(RowIndex(i),ColIndex(i),'r+','MarkerSize',50)
%     end



    eps = 0.01; % Epsilon
    IterNum = 0;
    while 1
        % E-step: Estimate membership given parameters 
        % Membership: The centroid that each colour is assigned to
        % Parameters: Location of centroids
        Dist = pdist2(Points,Centroids,'euclidean');

        [~, WhichCentroid] = min(Dist,[],2);

        % M-step: Estimate parameters given membership
        % Membership: The centroid that each colour is assigned to
        % Parameters: Location of centroids
        % TODO: Vectorize this part!
        OldCentroids = Centroids;
        for i = 1 : K
            PointsInCentroid = Points((find(WhichCentroid == i))',:);
            NumOfPoints = size(PointsInCentroid,1);
            % Note that NumOfPoints is never equal to 0, as a result of
            % the initialization. Or .... ???????
            if NumOfPoints ~= 0 
                Centroids(i,:) = sum(PointsInCentroid , 1) / NumOfPoints ;
            end
        end    

        % Check for convergence: Here we use the L2 distance
        IterNum = IterNum + 1;
        Margins = sqrt(sum((Centroids - OldCentroids).^2, 2));
        if sum(Margins > eps) == 0
            break;
        end

    end
    IterNum;
    Centroids ;


    % Load the larger image
    [LargerImage,ColorMap] = imread('bird_large.tiff');
    LargerImage = double(LargerImage);
    [largeRows,largeCols,~] = size(LargerImage);  % RGB is always 3 
    % Dist = zeros(size(Centroids,1),RGB);
    % TODO: Vectorize this part!

    % Replace each of the pixel with the nearest centroid    
    for i = 1 : largeRows 
        for j = 1 : largeCols
            Dist = pdist2(Centroids,reshape(LargerImage(i,j,:),1,RGB),'euclidean');
            [~,WhichCentroid] = min(Dist);            
            LargerImage(i,j,:) = Centroids(WhichCentroid);

        end
    end

    % Display new image
    imshow(uint8(round(LargerImage)),ColorMap)
    imwrite(uint8(round(LargerImage)), 'D:\Hoctap\bird_kmeans.tiff');

1 个答案:

答案 0 :(得分:2)

您使用单个线性索引将Centroids编入索引。

Centroids(WhichCentroid)

这将返回单个值(特别是该质心的红色值)。将此值分配给LargerImage(i,j,:)时,它会为所有RGB通道分配相同的值,从而生成灰度图像。

您可能希望获取所选质心的所有列,以提供要分配给LargerImage(i,j,:)的红色,绿色和蓝色值数组。您可以使用冒号:来指定属于Centroids指示的行的WhichCentroid的所有列。

LargerImage(i,j,:) = Centroids(WhichCentroid,:);
相关问题