如何在3D矩阵中使用数组作为索引?

时间:2016-05-23 15:21:16

标签: matlab matrix indexing

您好我已经加载了图像,因此创建了一个3D矩阵。

img1 = imread('bluebird.jpg')

我知道对于一个向量,我可以根据逻辑测试创建另一个向量,并将此另一个向量用作索引,如下所示:

speeds = [20 77 55 90 87 65 67 72 55]
invalid = speed > 70
speeds(invalid) = 0

这会将speeds中的所有无效速度设置为0。

但我还没弄明白如何使用3D矩阵(图像)。

我想要做的是为每个像素交换颜色分量1(红色)和3(蓝色),其中蓝色分量比三个分量的平均值(灰度)至少高20%。

我试过这个:

img1 = imread('bluebird.jpg');
img2 = img1;
m = mean(img1, 3);
blues = img1(:,:,3) > 1.2*m;
img2(blues, [3,2,1]) = img1(blues, [1,2,3]);

但那没用。变量blues成功获得了我想要的像素(具有显性蓝色成分的像素),但我在最后一行得到了非法语法。

有可能做我想要的吗?如果是这样,怎么样?

提前致谢。

3 个答案:

答案 0 :(得分:3)

问题是因为您的逻辑数组是2D(处理前两个维度),而您的线性索引仅应用于第三维。你可以组合逻辑索引,但是你必须有一个每维的数组。

data = magic(3);
data([true false, true], [1 3])

%   8   6
%   4   2

对于您的情况,一个简单的方法是将您的输入重新整形为[M*N x 3]数组然后您可以完全按照您的意愿执行,因为您的逻辑数组现在将是长度为M*N的列向量

img1 = imread('bluebird.jpg');

% Remember the original size
shape = size(img1);

% Reshape to (M*N x 3)
img2 = reshape(img1, [], 3);

isBlue = img2(:,3) > 1.2 * mean(img2, 2);
img2(isBlue, [3 2 1]) = img2(isBlue, [1 2 3]);

% Reshape it back to the original size
img2 = reshape(img2, shape);

或者您只需拨打fliplr

,而不是使用索引编制
img1 = imread('bluebird.jpg');

% Remember the original size
shape = size(img1);

% Reshape to (M*N x 3)
img2 = reshape(img1, [], 3);

isBlue = img2(:,3) > 1.2 * mean(img2, 2);
img2(isBlue, :) = fliplr(img2(isBlue, :));

% Reshape it back to the original size
img2 = reshape(img2, shape);

这比创建3D逻辑矩阵更有效,因为reshape命令非常便宜,因为它们实际上并没有改变基础数据。

答案 1 :(得分:1)

逻辑索引(使用矩阵)和整数索引不能混用。 相反,您可以构造完整的逻辑索引矩阵:

img2 = rand(2, 4, 3);
m = mean(img2, 3);
blues = img2(:,:,3) > 1.2*m;
f_ind = false(size(blues));
ind = cat(3, blues, f_ind, blues);
img2(ind) = cat(3, img2(cat(3, f_ind, f_ind, blues)), img2(cat(3, blues, f_ind, f_ind)));

或者,而不是最后两行:

r_ind = cat(3, blues, f_ind, f_ind);
b_ind = cat(3, f_ind, f_ind, blues);
img2(b_ind) = img1(r_ind);
img2(r_ind) = img1(b_ind);

答案 2 :(得分:1)

使用:

[Y,X] = find(blues);
inds1 = sub2ind(size(img1),Y,X,ones(length(Y),1));
inds2 = sub2ind(size(img1),Y,X,3*ones(length(Y),1));
img2([inds1,inds2]) = img1([inds2,inds1]);
相关问题