我有一个大小为RGB uint8(576,720,3)
的图像,我想将每个像素分类为一组颜色。我已经使用rgb2lab
从RGB转换为LAB空间,然后删除了L层,因此它现在是由{AB}组成的double(576,720,2)
。
现在,我想将此分类为我在另一张图像上训练过的一些颜色,并将它们各自的AB表示计算为:
Cluster 1: -17.7903 -13.1170
Cluster 2: -30.1957 40.3520
Cluster 3: -4.4608 47.2543
Cluster 4: 46.3738 36.5225
Cluster 5: 43.3134 -17.6443
Cluster 6: -0.9003 1.4042
Cluster 7: 7.3884 11.5584
现在,为了将每个像素分类/标记为1-7簇,我现在执行以下操作(伪代码):
clusters;
for each x
for each y
ab = im(x,y,2:3);
dist = norm(ab - clusters); // norm of dist between ab and each cluster
[~, idx] = min(dist);
end
end
然而,由于图像分辨率和我手动遍历每个x和y,这非常慢(52秒)。
我可以使用哪些内置函数执行相同的工作?必须有。
总结:我需要一种分类方法,将像素图像分类为已定义的一组聚类。
答案 0 :(得分:11)
对于N x 2
大小的点/像素数组,您可以避免other solution by Luis中建议的permute
,这可能会使某些事情变慢,有{{1}它的版本以及让"permute-unrolled"
向bsxfun
数组而不是2D
数组工作,这对于性能必须更好。
因此,假设要将集群排序为3D
大小的数组,您可以尝试使用其他基于N x 2
的方法 -
bsxfun
您可以尝试另一种利用fast matrix multiplication in MATLAB
并基于this smart solution的方法 -
%// Get a's and b's
im_a = im(:,:,2);
im_b = im(:,:,3);
%// Get the minimum indices that correspond to the cluster IDs
[~,idx] = min(bsxfun(@minus,im_a(:),clusters(:,1).').^2 + ...
bsxfun(@minus,im_b(:),clusters(:,2).').^2,[],2);
idx = reshape(idx,size(im,1),[]);
让我们考虑两个矩阵d = 2; %// dimension of the problem size
im23 = reshape(im(:,:,2:3),[],2);
numA = size(im23,1);
numB = size(clusters,1);
A_ext = zeros(numA,3*d);
B_ext = zeros(numB,3*d);
for id = 1:d
A_ext(:,3*id-2:3*id) = [ones(numA,1), -2*im23(:,id), im23(:,id).^2 ];
B_ext(:,3*id-2:3*id) = [clusters(:,id).^2 , clusters(:,id), ones(numB,1)];
end
[~, idx] = min(A_ext * B_ext',[],2); %//'
idx = reshape(idx, size(im,1),[]); %// Desired IDs
和A
我们想要计算距离矩阵。为了便于下面的简单解释,我们将B
视为A
和3 x 2
作为B
大小的数组,从而表明我们正在使用X-Y点。如果我们将4 x 2
作为A
和N x 3
作为B
大小的数组,则那些将是M x 3
个点。
现在,如果我们必须手动计算距离矩阵的平方的第一个元素,它将看起来像这样 -
X-Y-Z
将是 -
first_element = ( A(1,1) – B(1,1) )^2 + ( A(1,2) – B(1,2) )^2
现在,根据我们提出的矩阵乘法,如果在早期代码中的循环结束后检查first_element = A(1,1)^2 + B(1,1)^2 -2*A(1,1)* B(1,1) + ...
A(1,2)^2 + B(1,2)^2 -2*A(1,2)* B(1,2) … Equation (1)
和A_ext
的输出,它们将如下所示 -
因此,如果在B_ext
和A_ext
的转置之间执行矩阵乘法,则乘积的第一个元素将是B_ext
和{的第一行之间的元素乘法的总和。 {1}},即这些的总和 -
结果与先前从A_ext
获得的结果相同。 B_ext
的所有元素都会针对Equation (1)
中与A
位于同一列中的所有元素继续这样做。因此,我们最终会得到完整的平方距离矩阵。这就是全部!!
基于矩阵乘法的距离矩阵计算的矢量化变体是可能的,尽管它们没有看到任何大的性能改进。接下来列出了两个这样的变化。
变体#1
B
变体#2
A
所以,这些也可以被视为实验版本。
答案 1 :(得分:4)
使用pdist2
(统计工具箱)以矢量化方式计算距离:
ab = im(:,:,2:3); % // get A, B components
ab = reshape(ab, [size(im,1)*size(im,2) 2]); % // reshape into 2-column
dist = pdist2(clusters, ab); % // compute distances
[~, idx] = min(dist); % // find minimizer for each pixel
idx = reshape(idx, size(im,1), size(im,2)); % // reshape result
如果您没有统计工具箱,则可以用
替换第三行dist = squeeze(sum(bsxfun(@minus, clusters, permute(ab, [3 2 1])).^2, 2));
这给出了平方距离而不是距离,但是为了最小化它并不重要。