matlab中如何从矩阵中删除特定值
我有图像矩阵420x700,我想删除每行中的特定值,更改图像尺寸。这就像从中删除一列,但不是直线,变成420x699图像。我应该水平保留删除值之前的值,并将删除值之后的所有值向后移动1个位置matlab中如何从矩阵中删除特定值,matlab,image-processing,matrix,Matlab,Image Processing,Matrix,我有图像矩阵420x700,我想删除每行中的特定值,更改图像尺寸。这就像从中删除一列,但不是直线,变成420x699图像。我应该水平保留删除值之前的值,并将删除值之后的所有值向后移动1个位置 RGB = imread('image.jpg'); I1 = RGB(:,:,1); 如何做到这一点?这是一个好问题,如果没有for循环,我想不出实现这一点的方法 假设M是要从中删除列的nr by nc矩阵,R是nr-by-1向量,每行上都有要删除的元素的列索引 以下代码创建了一个新的矩阵a,其中“列”
RGB = imread('image.jpg');
I1 = RGB(:,:,1);
如何做到这一点?这是一个好问题,如果没有for循环,我想不出实现这一点的方法 假设
M
是要从中删除列的nr by nc
矩阵,R
是nr-by-1
向量,每行上都有要删除的元素的列索引
以下代码创建了一个新的矩阵a
,其中“列”从M
中删除,向量B
中删除了元素:
[nr,nc]=尺寸(M);
A=零(nr,nc-1,'like',M);
B=零(nr,1,'like',M);
对于k=1:nr
r=r(k);
t=[1:r-1,r+1:nc];
A(k,:)=M(k,t);
B(k)=M(k,r);
结束
@bicker和@Cris是正确的,但为了增加一些味道,我尝试演示另一种方法-使用线性索引,这可以在MATLAB中讲授有关二维数组的列主索引的有趣课程
另一点需要注意的是,这种过程是接缝雕刻算法中所遵循的,我们以这种方式移除垂直接缝
加载一个测试图像来运行它-裁剪它以便更容易地分析
I = imread('peppers.png');
I = I(100:100+9, 100:100+19, :);
figure, imshow(I)
创建指示要删除哪些像素的遮罩。这模拟了我认为您所指向的条件—在本例中,我们为要删除的每一行选择随机列索引。您可能会将此信息作为输入
mask = zeros(size(I, [1:2]), 'logical');
for idx = 1:size(mask, 1)
randidx = randi(size(mask, 2));
mask(idx, randidx) = 1;
end
figure, imshow(mask)
使用列主线性索引技巧可以更快地删除!因为我们一次删除一列,所以我们将图像旋转90度,并将此问题转化为一次删除一行。MATLAB“垂直”索引,因此我们可以使用线性索引一次删除所有遮罩像素(而不是一次删除一行/列),然后使用“重塑”恢复形状,最后旋转回原始方向
It = rot90(I);
maskt = rot90(mask);
% Preallocate output
Ioutput = zeros([size(I, 1), size(I, 2) - 1, size(I, 3)], 'like', I);
for nchannel = 1:3
Icropped = It(:, :, nchannel);
% MATLAB indexes column wise - so, we can use linear indexing to make
% this computation simpler!
Icropped = Icropped(maskt(:) == 0);
Icropped = reshape(Icropped, [size(maskt, 1) - 1, size(maskt, 2)]);
% Restore the correct orientation after removing element!
Icropped = rot90(Icropped, 3);
Ioutput(:, :, nchannel) = Icropped;
end
figure, imshow(Ioutput)
我裁剪了“辣椒”的图片来演示这一点,这样你就可以说服自己这是正确的。这种方法同样适用于较大的图像。对于图像中的每一行
r
,将该行存储在临时数组中,删除所需元素,然后将修改后的数组复制到行r
处的输出图像。我想您的操作与您描述的完全相同:对于每一行,将所选索引后的值向后移动1个位置。那么你就可以删除最后一列了。我认为这是不对的。您应该使用转置,而不是使用rot90
,并且两次转置(前后)的成本远远超过在大型矩阵的行之间迭代的成本,所以这种方法实际上比使用for循环要慢。@JonathanH——我已经手动测试了旋转的想法——因为删除一列中的像素独立于其他列,所以旋转应该与转置相同。我们只需要将“方向”设置为“垂直”。我没有做过严格的性能测试,所以您可能是正确的w.r.t。传统的方法速度更快。因此,我在这里编辑/删除了答案中的性能声明。谢谢分享你的想法!感谢您在本例中提出了一种避免for循环的有趣方法!这是相当巧妙的,尽管这可能不是最有效的方法。:)