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

问题描述

我是Julia的新手,我正在尝试了解基本的数据可视化。我正在使用以下方法创建2D噪声数组:

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

结果数组如下所示(左)。我想确定特定的像素-由具有长度,宽度和旋转度的矩形定义-并将这些值设置为已知数字。最终,我想要类似下图(右)所示的图像。

我没有程序包的偏好设置,但是我一直在查看Images,OpenCV等。我希望有一种直接的方法来实现此目的。

enter image description here

解决方法

我想识别特定的像素-由具有长度,宽度和旋转度的矩形定义

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

这是一个简单的代码,为您提供了一个示例,您可以执行此操作(效率不是很高,但足够快用于演示目的):

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,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

rotated_rectangle_on_black

现在,您可以提取变换矩阵并在其他地方使用它,而不是直接用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,aspect_ratio = 1)
end

using Luxor

function b()
    Drawing(300,1)
    Luxor.translate(100,60)
    Luxor.rotate(-10 * pi / 180)
    w = 40
    h = 200
    rect(O,:fill)
    finish()
    preview()

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

    a(tranformation_matrix)
end

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

rotated_rectangle_on_heatmap

关于朱莉娅阴谋的警告:

第一次绘图的时间很慢。为了对其进行任何真正的迭代,您应该利用Revise.jl并将测试功能保存在文件中,并将其包含在includet("test.jl")中。然后,您的julia会话将持续进行,您只需等待一次using语句即可。