首页 > 解决方案 > 我想在 Julia 中对图像进行逻辑屏蔽

问题描述

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

mask = img[:, :, 2] .== img[:, :, 3]
img[:, :, 2][mask] .= 0

图像大小为 (1200, 1920, 3),但 img[:, :, 2] 的大小为 (1676348,)。
我猜掩码上的“真”值仍然存在,但“假”值被删除。
我想将逻辑屏蔽图像作为图像处理,因此它应该是 (1200, 1920, 1)。
如何通过逻辑屏蔽保持大小?

标签: julia

解决方案


编辑:

快速的方法是:

@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

推荐阅读