在 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)
在其中 - 我认为假设您传递矩形的三个顶点 x1
、x2
和 x3
(而不是传递旋转、缩放和平移)会更容易(假设它的边是由 x1-x2
和 x1-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
语句一次。
我是 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)
在其中 - 我认为假设您传递矩形的三个顶点 x1
、x2
和 x3
(而不是传递旋转、缩放和平移)会更容易(假设它的边是由 x1-x2
和 x1-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
语句一次。