Image 将图像中的多个像素值替换为某个值

Image 将图像中的多个像素值替换为某个值,image,matlab,image-processing,Image,Matlab,Image Processing,我有一张640x480的图像img,我想用一个特定的值10,来替换不在这个列表或数组中的像素x=[1,2,3,4,5],这样img中没有x中任何值的任何像素都将被替换为10。我已经知道如何使用img(img~=1)=10替换一个值,或者使用这个img(img~=1&img~=2&img~=3&img~=4&img~=5)=10替换多个值,但是当我尝试这个img(img~=x)=10时,它给出了一个错误,说矩阵维度必须一致。因此,如果有人可以提供建议。您可以通过和的组合轻松实现这一点。我们可以创建

我有一张640x480的图像
img
,我想用一个特定的值
10
,来替换不在这个列表或数组中的像素
x=[1,2,3,4,5]
,这样
img
中没有
x
中任何值的任何像素都将被替换为
10
。我已经知道如何使用
img(img~=1)=10替换一个值,或者使用这个
img(img~=1&img~=2&img~=3&img~=4&img~=5)=10替换多个值,但是当我尝试这个
img(img~=x)=10
时,它给出了一个错误,说
矩阵维度必须一致
。因此,如果有人可以提供建议。

您可以通过和的组合轻松实现这一点。我们可以创建一个由
[1,2,3,4,5]
元素组成的3D列向量,然后在图像(假设灰度)上使用
bsxfun
和不等于方法(
@ne
),从而创建一个包含5个切片的3D矩阵。每个切片将告诉您图像中的位置是否与
x
中的元素不匹配。第一个片段将为您提供与
x=1
不匹配的位置,第二个片段将为您提供与
x=2
不匹配的位置,依此类推

完成此操作后,我们可以使用对第三维操作的调用来合并不等于所有1、2、3、4或5的像素位置。最后一步是采用这个
逻辑
映射,它告诉您不是1、2、3、4或5的位置,我们将这些位置设置为10

我们需要考虑的是图像类型和向量<代码> x>代码>必须是同一类型。我们可以通过将向量转换为与

img
相同的类来确保这一点

因此,请执行以下操作:

x = permute([1 2 3 4 5], [3 1 2]);
vals = bsxfun(@ne, img, cast(x, class(img)));
ind = all(vals, 3);
img(ind) = 10;
ind = true(size(img));
for idx = 1 : 5
    ind = ind & img ~= idx;
end
img(ind) = 10;
上述方法的优点是,用于检查元素的列表可以是您想要的任何列表。它可以防止出现混乱的逻辑索引语法,如
img(img~=1&img~=2&..)
。您所要做的就是更改代码开始行的输入列表,
bsxfun
permute
任何
都应该为您完成这项工作

下面是一个示例5 x 5图像:

>> rng(123123);
>> img = randi(7, 5, 5)

img =

     3     4     3     6     5
     7     2     6     5     1
     3     1     6     1     7
     6     4     4     3     3
     6     2     4     1     3
通过使用上述代码,我们得到的输出是:

img =

     3     4     3    10     5
    10     2    10     5     1
     3     1    10     1    10
    10     4     4     3     3
    10     2     4     1     3
您可以非常肯定地看到,那些既不是1、2、3、4或5的元素被设置为10

在一边 如果您不喜欢
permute
bsxfun
方法,一种方法是使用
for
循环,并使用最初的all
true
数组,使用一个
logical
映射保持逻辑与最终结果的and,该映射由不等于
x
中每个值的位置组成。最后,我们将有一个逻辑映射,其中
true
是那些既不等于1、2、3、4或5的位置

因此,请这样做:

x = permute([1 2 3 4 5], [3 1 2]);
vals = bsxfun(@ne, img, cast(x, class(img)));
ind = all(vals, 3);
img(ind) = 10;
ind = true(size(img));
for idx = 1 : 5
    ind = ind & img ~= idx;
end
img(ind) = 10;
如果你这样做,你会发现我们得到了相同的答案。

方法#1

你可以用, 根据
ismember(a,B)
案例的官方文档,它将输出一个与
a
大小相同的逻辑数组,其中
1
B
中的任何元素都存在于
A
0
,否则。由于您希望检测到
“不在列表或数组中”
,因此需要在之后将其反转,即
~ismember()

在您的例子中,您有
img
作为
A
x
作为
B
,因此
~ismember(img,x)
将为您提供
img~=x中任何元素的位置
然后,您可以映射到
img
,使用此最终解决方案将其中的所有值设置为
10
-

img(~ismember(img,x)) = 10

方法#2

与类似,您可以使用,但将其保留在
2D
中,这样会更有效,因为它还可以避免
permute
。实现看起来像这样-

img(reshape(all(bsxfun(@ne,img(:),x(:).'),2),size(img))) = 10

非常有趣的问题!一个我已经想了很多次并解决了的问题。谢谢你的提问:)@shepherd:IMHO,
ismember
方法是兼顾内存和可读性的方法。@Jonas同意这两种观点!