【问题标题】:K-means for image compression only gives black-and-white result用于图像压缩的 K-means 仅给出黑白结果
【发布时间】:2016-10-09 02:41:29
【问题描述】:

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

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

这是我的代码:

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');

【问题讨论】:

    标签: algorithm matlab k-means


    【解决方案1】:

    您正在使用单个线性索引对 Centroids 进行索引。

    Centroids(WhichCentroid)
    

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

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

    LargerImage(i,j,:) = Centroids(WhichCentroid,:);
    

    【讨论】:

    • 谢谢你,好先生!像魅力一样工作!我可以问一些在 Matlab 中调试的技巧吗?我真的不想再犯这种错误了:(
    • @DangManhTruong 这种事情实际上很难检测到,因为没有警告。除了小心之外,真的没有万无一失的方法可以避免这种事情。
    • 谢谢。顺便说一句,在练习中作者说大约需要 30 到 100 次迭代,但在我的代码中,算法在“while”循环中需要 149 次迭代才能收敛。这是否意味着我的实现有些拙劣? :(
    猜你喜欢
    • 2017-08-09
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 2018-04-30
    • 2013-04-22
    • 1970-01-01
    相关资源
    最近更新 更多