矩阵计算

时间:2014-09-07 13:49:10

标签: matlab matrix

我有一个384*512*3 RGB矩阵。只有512个独特的颜色可以用不同的权重重复。从他们,我必须选择一半,另一半必须用第一个最接近的元素替换。

我想过循环遍历图像,并搜索当前颜色的最接近的颜色。找到后,我将其中一个替换为另一个。

但我有3个循环1:3841:5121:256。前两个I循环通过RGB矩阵,第三个用于循环到包含最终颜色的矩阵。这需要一些时间来计算。

可以做些什么来加快速度?

循环看起来像这样:

dim=size(RGB);
for i=1:dim(1)
    for j=1:dim(2)
        aux=[RGB(i,j,1) RGB(i,j,2) RGB(i,j,3)];
        minim=RGB_dist(uint8(V_colors_K(1,1:3)),aux);
        index=1;
            for k=1:K
            %index=1;
            if (minim>RGB_dist(uint8(V_colors_K(k,1:3)),aux))
                minim=RGB_dist(uint8(V_colors_K(k,1:3)),aux);
                index=k

            end
            RGB(i,j,1)=V_colors_K(index,1);
            RGB(i,j,2)=V_colors_K(index,2);
            RGB(i,j,3)=V_colors_K(index,3);
        end
    end
end

V_colors_K代表被选为最终颜色的半色。

我可以考虑一些小的改进。如果颜色在good一半中,则不需要最小距离。

这里的算法更精确:

定义1.函数D(c1,c2)是距离 在两个颜色矢量c1和c2之间,例如 欧氏距离。

定义2.函数P(c)是像素数 颜色c。 定义3.初始颜色集的基色cbase Q是满足等式的颜色

enter image description here

定义4.颜色c,V(c)的加权乘积, 定义为

enter image description here

其中wp是像素数的权重, 和wd是颜色距离的权重。

给定第一个颜色cbase,我们的方法计算 其他颜色和选择的加权产品 第一个K-1最大的产品。相应的 使用具有基色的K-1颜色 形成一个初始调色板。左N-K颜色与初始中最接近的颜色合并 用于生成最终调色板的调色板。

RGB_dist功能:

function[distance]=RGB_dist(x,y)

    distance=sqrt(sum((double(x-y)).^2*[3;4;2],2));

end

我有一个适用于整个矩阵的函数,它计算所有对之间的距离。

function[D]=RGB_dist_full_2(x)

I = nchoosek(1:size(x,1),2);

D = squareform(RGB_dist(x(I(:,1),:), x(I(:,2),:)))

end

然后,我需要在每列上得到最小值。

3 个答案:

答案 0 :(得分:1)

如果我正确阅读此内容,则您将RGB_dist()成对操作应用于V_colors_k中的每种颜色和RBG中的每个像素。如果RGB_dist()是线性函数,就像点积,那么您可以一次性将它应用于整个矩阵。例如,如果它是点积,那么您可以用:

替换整个内循环
DISTS = V_colors_K * RGB(i,j,:)';
k = find( DISTS == min(DISTS(:)) );
RGB(i,j,:) = V_colors_K(k,:);

不知道RBG_dist()中的内容我无法给你一个更好的答案。我能给出的一般答案是:Matlab循环很慢,如果你想让它快速运行,你需要删除所有循环并只使用矩阵运算(快速闪烁)。用矩阵操作替换循环的过程称为矢量化代码,这可能很棘手。如果不知道你在RBG_dist()内做了什么,就不可能为你提供完整的矢量化。

我在matlab中的常用工作流程是用循环的直观方式编写一些东西,就像你一样,然后一旦它给我正确的结果我回过头来弄清楚如何向量化它(即用矩阵运算替换所有循环)到快一点。矢量化是棘手的,它就像一个线性代数拼图,加速总是比我首先编写代码花费更长的时间。

更新:

我得到的最好的就是在你的基色上使用一个循环。你与RGB_dist函数非常接近,因为该行在整个矩阵中都能很好地工作:

[RGBwidth RGBHeight RGBdepth] = size(RGB);
minDists=inf( [RGBwidth RGBheight] );
bestKs=zeros( [RGBwidth RGBheight] );
for k=1:K
    % make matrix out of the color k, the same shape as RGB
    color_K_mat = premute(repmat(V_colors_K(k,:), [RGBwidth 1 RGBheight]), [3 1 2]);

    % compute the distance from each pixel's color to color k
    dists = sqrt(sum((RGB-color_K_mat).^2, 3));

    % create a binary mask showing which pixels are closer to this color than to any previous one
    mask = (dists < minDists);

    % update your results matrices
    bestKs = not(mask)*bestKs + mask*k
    minDists = min(bestKs, dists);
end

% now bestKs(i,j) gives you the index k of the closest color for pixel (i,j)
% and minDists(i,j) gives you the distance to that color

理论上应该可以将这个循环矢量化,但这是一个更大的难题,我有自己的工作要做:P

答案 1 :(得分:0)

使用kmeans

img = im2double( img );
[IDX,C] = kmeans( reshape( img, [], 3 ), 256 ); %// cluster into 256 clusters
cimg = ind2rgb( reshape( IDX, size(img(:,:,1)) ), C );

答案 2 :(得分:0)

减少内循环操作:

  1. 定义一个V_colors_K大小的向量,所有值都指定为aux(让我们称之为v_aux)。
  2. 然后在v_aux与V_colors_K上计算RGB_dist。
  3. 取最小结果(表示最小距离颜色)。