在 Julia 中的数组中创建一个填充的矩形

Creating a filled rectangle within an array in Julia

我是 Julia 的新手,我正在尝试了解基本的数据可视化。我正在创建一个二维噪声阵列:

xRange, yRange = 1:1:300, 1:1:300
maxVal = 0.3
noiseArr = rand(length(xRange),length(yRange))*maxVal

生成的数组如下图(左)所示。我想识别特定像素——由具有长度、宽度和旋转的矩形定义——并将这些值设置为已知数字。最后,我想要如下图(右)所示的东西。

我没有软件包偏好,但我一直在查看图像、OpenCV 等。我希望有一种直接的方法可以做到这一点。

I would like to identify specific pixels -- defined by a rectangle with length, width, and rotation

知道长度、宽度和旋转不足以在平面上唯一定位矩形。你还需要翻译。

这是一个简单的代码,它向您展示了您可以做什么(它不是超级高效,但对于演示目的来说足够快):

function rectangle!(x1, x2, x3, noiseArr, val)
    A = [x2-x1 x3-x1]
    b = x1
    iA = inv(A)

    for i in axes(noiseArr, 1), j in axes(noiseArr, 2)
        it, jt = iA * ([i, j]-b)
        0 <= it <= 1 && 0 <= jt <= 1 && (noiseArr[i, j] = val)
    end
end

x1 = [40, 140]
x2 = [230, 100]
x3 = [50, 170]
rectangle!(x1, x2, x3, noiseArr, 0.0)

在其中 - 我认为假设您传递矩形的三个顶点 x1x2x3(而不是传递旋转、缩放和平移)会更容易(假设它的边是由 x1-x2x1-x3 对组成的)并且它会计算你需要的仿射变换。 val 是矩形内的像素应该得到的值。

请注意,本质上我们所做的是计算一个矩形的反向仿射变换回到单位正方形,并检查哪些点位于单位正方形内(这很容易)。

(正如上面的评论者所指出的那样——这不是最佳的方法,因为你做了很多不需要的计算,但我希望它有更容易理解的好处;还有好处Julia 就是写这样一个循环不是问题而且还是跑得够快)

这里有一个简单的例子,用 Luxor.jl

使用图元绘制它
using Luxor

function b()
    Drawing(300, 300, "hello-world.png")
    background("black")
    sethue("white")
    #Luxor.scale(1,1)
    Luxor.translate(150, 30)
    Luxor.rotate(10 * pi / 180)
    w = 40
    h = 200
    rect(O, w, h, :fill)
    finish()
    preview()
end

现在,您可以提取变换矩阵并在其他地方使用它,而不是直接用 Luxor 绘制它。

using Plots
using GR
using LinearAlgebra

gr(size = (300, 300), legend = false)

function a(transform=Matrix{Int}(I, 3, 3))
    side = 300
    width = side
    height = side
    xs = [string("x", i) for i = 1:width]
    ys = [string("y", i) for i = 1:height]
    z = float((1:height) * reshape(1:width, 1, :))
    # Plots.heatmap(xs, ys, z, aspect_ratio = 1)

    white = maximum(z)

    # Draw a rectangle with a rotation matrix applied
    for x in 0:40
        for y in 0:200
            t = transform*[x;y;1]
            z[round(Int, t[2]), round(Int, t[1])] = white
        end
    end

    Plots.heatmap(xs, ys, z, aspect_ratio = 1)
end

using Luxor

function b()
    Drawing(300, 300, "hello-world.png")
    background("black")
    sethue("white")
    #Luxor.scale(1,1)
    Luxor.translate(100, 60)
    Luxor.rotate(-10 * pi / 180)
    w = 40
    h = 200
    rect(O, w, h, :fill)
    finish()
    preview()

    tranformation_matrix = Luxor.cairotojuliamatrix(Luxor.getmatrix())

    a(tranformation_matrix)
end

请注意,这会留下杂散像素,因为我的 for 循环在栅格化填充方面效率不高。从 Luxor 访问像素数据可能更好,或者使用其他一些将仿射变换应用于矩阵的函数。

关于 julia 情节的注意事项:

第一个情节的时间很慢。要对其进行任何真正的迭代,您应该利用 Revise.jl 并将您的测试函数保存在一个文件中,并将其包含在 includet("test.jl") 中。然后你的 julia 会话是持久的,你只需要等待你的 using 语句一次。