我想在Julia的图像上做逻辑掩蔽

我想在Julia的图像上做逻辑掩蔽,julia,Julia,我想在Julia中进行逻辑掩蔽。 如果图像的第二个和第三个元素相等,则应将它们更改为0,其他元素不应更改。 我试过这个 mask = img[:, :, 2] .== img[:, :, 3] img[:, :, 2][mask] .= 0 图像大小为(120019203),但img[:,:,2]的大小为(1676348,)。 我猜掩码上的“真”值会保留,但“假”值会被删除。 我想将逻辑屏蔽图像作为图像处理,因此它应该是(120019201)。 如何使用逻辑屏蔽保持大小?编辑: 最快的方法是:

我想在Julia中进行逻辑掩蔽。
如果图像的第二个和第三个元素相等,则应将它们更改为0,其他元素不应更改。
我试过这个

mask = img[:, :, 2] .== img[:, :, 3]
img[:, :, 2][mask] .= 0
图像大小为(120019203),但img[:,:,2]的大小为(1676348,)。
我猜掩码上的“真”值会保留,但“假”值会被删除。
我想将逻辑屏蔽图像作为图像处理,因此它应该是(120019201)。
如何使用逻辑屏蔽保持大小?

编辑:

最快的方法是:

@views @. img[:, :, 2] *= img[:, :, 2] != img[:, :, 3]
这里有一个基准:

julia> img = rand(1:3, 10000, 10000, 3);

julia> @time @views @. img[:, :, 2] *= img[:, :, 2] != img[:, :, 3];
  0.111409 seconds (28 allocations: 1.219 KiB)

有其他方法可以满足您的要求,但如果我们希望遵循您的实施,请执行以下操作:

julia> img = rand(1:3, 4,4,3)
4×4×3 Array{Int64,3}:
[:, :, 1] =
 1  3  2  3
 1  1  1  3
 3  2  1  3
 2  2  3  1

[:, :, 2] =
 1  2  3  2
 2  2  1  1
 3  3  3  2
 1  3  2  1

[:, :, 3] =
 3  2  2  2
 3  2  2  1
 3  2  3  3
 2  2  1  2

julia> mask = img[:, :, 2] .== img[:, :, 3]
4×4 BitArray{2}:
 0  1  0  1
 0  1  0  1
 1  0  1  0
 0  0  0  0

julia> view(img,:, :, 2)[mask] .= 0;

julia> img
4×4×3 Array{Int64,3}:
[:, :, 1] =
 1  3  2  3
 1  1  1  3
 3  2  1  3
 2  2  3  1

[:, :, 2] =
 1  0  3  0
 2  0  1  0
 0  3  0  2
 1  3  2  1

[:, :, 3] =
 3  2  2  2
 3  2  2  1
 3  2  3  3
 2  2  1  2
(使用
view
获取所需内容非常重要,否则
img[:,:,2]
会创建副本)

或者,在Julia中,使用循环编写相同的代码非常简单,例如:

function applymask!(img)
    for i in axes(img, 1), j in axes(img, 2)
        img[i, j, 2] == img[i, j, 3] && (img[i, j, 2] = 0)
    end
end
(这不是最快的实现,因为它使用分支并进行边界检查,但在大多数情况下应该足够好)

现在你可以写:

julia> img = rand(1:3, 4,4,3)
4×4×3 Array{Int64,3}:
[:, :, 1] =
 1  3  1  3
 3  3  1  2
 3  3  3  3
 2  1  3  1

[:, :, 2] =
 3  1  3  1
 3  3  3  3
 2  1  1  3
 1  2  3  3

[:, :, 3] =
 1  1  2  1
 2  1  3  2
 3  3  1  1
 1  2  1  3

julia> applymask!(img)

julia> img
4×4×3 Array{Int64,3}:
[:, :, 1] =
 1  3  1  3
 3  3  1  2
 3  3  3  3
 2  1  3  1

[:, :, 2] =
 3  0  3  0
 3  3  0  3
 2  1  0  3
 0  0  3  0

[:, :, 3] =
 1  1  2  1
 2  1  3  2
 3  3  1  1
 1  2  1  3

编写您所要求的内容的最佳方法可能是
img[mask,2].=0
,但这对Julia直到1.5都不起作用。作为一种解决方法,您可以使用
@view
创建可变切片:

julia> img = cat([1 2; 3 4], [1 5; 6 7]; dims=3)
2×2×2 Array{Int64, 3}:
[:, :, 1] =
 1  2
 3  4

[:, :, 2] =
 1  5
 6  7

julia> mask = img[:,:,1] .== img[:,:,2]
2×2 BitMatrix:
 1  0
 0  0

julia> v = @view img[:,:,2]
2×2 view(::Array{Int64, 3}, :, :, 2) with eltype Int64:
 1  5
 6  7

julia> v[mask] .= 0
1-element view(reshape(view(::Array{Int64, 3}, :, :, 2), 4), [1]) with eltype Int64:
 0

julia> img
2×2×2 Array{Int64, 3}:
[:, :, 1] =
 1  2
 3  4

[:, :, 2] =
 0  5
 6  7
值得强调的是,如果没有
@视图
v=img[:,:,2]
将创建
img
片段的副本,因此对
v
所做的任何更改都不会反映在
img
中。该视图确保
v
img
保持耦合

图像大小为(120019203),但img[:,:,2]的大小为(1676348,)

为了准确起见,我应该指出那不是真的。使用上面的
img

julia> size(img[:,:,2])
(2, 2)

A将此应用于(1200、1920、3)图像,大约需要3秒钟。我希望在1秒内完成此过程。你知道更多更快的方法吗?对不起,Bogumil,我应该在发布之前刷新,谢谢你回答这个问题。@Koney,你确定那不是编译时吗?这应该是瞬间的。@tholy-事实上,很高兴有你对此发表评论。我在我的答案中添加了一个编辑,显示了一种更有效的方式来完成要求的任务。@Kotaro-我在我的答案中添加了一个基准,它比你的矩阵大70倍,运行时间为0.1秒。从Julia 1.6开始,可能支持语法
img[mask,2].=0
,请参阅。