我有一个384*512*3 RGB矩阵。只有512独特的颜色,重复自己与不同的权重。从它们中,我必须选择一半,而另一半必须替换为第一个元素中最接近的元素。
我想通过循环的图像,并搜索最近的颜色为当前的一个。在找到它之后,我用另一个代替它。
但我有三个循环1:384,1:512,1: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
endV_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函数:
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然后,我需要得到每一列的最小值。
发布于 2014-09-07 17:28:42
如果我正确阅读,您将对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理论上,即使这个循环也可以矢量化,但这是一个更大的难题,我有自己的工作要做:
发布于 2014-09-07 14:33:12
使用kmeans
img = im2double( img );
[IDX,C] = kmeans( reshape( img, [], 3 ), 256 ); %// cluster into 256 clusters
cimg = ind2rgb( reshape( IDX, size(img(:,:,1)) ), C );发布于 2014-09-07 17:27:50
要减少内环操作:
https://stackoverflow.com/questions/25710892
复制相似问题