首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >矩阵计算

矩阵计算
EN

Stack Overflow用户
提问于 2014-09-07 13:49:09
回答 3查看 83关注 0票数 0

我有一个384*512*3 RGB矩阵。只有512独特的颜色,重复自己与不同的权重。从它们中,我必须选择一半,而另一半必须替换为第一个元素中最接近的元素。

我想通过循环的图像,并搜索最近的颜色为当前的一个。在找到它之后,我用另一个代替它。

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

怎样才能加快速度呢?

这些循环看起来如下:

代码语言:javascript
复制
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.初始颜色集q的基色c基是满足方程的颜色

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

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

在给定第一个颜色基的情况下,我们的方法计算其他颜色的加权乘积,并选择第一个K-1最大乘积。与基色对应的K-1颜色用于形成初始调色板.左N颜色与初始调色板中最接近的颜色合并,生成最终调色板。

RGB_dist函数:

代码语言:javascript
复制
function[distance]=RGB_dist(x,y)

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

end

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

代码语言:javascript
复制
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

然后,我需要得到每一列的最小值。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-09-07 17:28:42

如果我正确阅读,您将对RGB_dist()操作对V_colors_k中的每一种颜色和RBG中的每个像素进行二次应用。如果RGB_dist()是一个线性函数,就像一个点积,那么你可以一次把它应用到整个矩阵中。例如,如果它是一个点积,那么您可以用以下内容替换整个内循环:

代码语言:javascript
复制
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函数,因为这条线在整个矩阵上都能很好地工作:

代码语言:javascript
复制
[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

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

票数 1
EN

Stack Overflow用户

发布于 2014-09-07 14:33:12

使用kmeans

代码语言:javascript
复制
img = im2double( img );
[IDX,C] = kmeans( reshape( img, [], 3 ), 256 ); %// cluster into 256 clusters
cimg = ind2rgb( reshape( IDX, size(img(:,:,1)) ), C );
票数 0
EN

Stack Overflow用户

发布于 2014-09-07 17:27:50

要减少内环操作:

  1. 定义一个大小为V_colors_K的向量,将所有值赋值为aux (让我们称它为v_aux)。
  2. 然后计算RGB_dist上的v_aux和V_colors_K。
  3. 取最小结果(表示最小距离颜色)。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25710892

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档