问题描述
我是Julia的新手,我正在尝试了解基本的数据可视化。我正在使用以下方法创建2D噪声数组:
xrange,yRange = 1:1:300,1:1:300
maxVal = 0.3
noiseArr = rand(length(xrange),length(yRange))*maxVal
结果数组如下所示(左)。我想确定特定的像素-由具有长度,宽度和旋转度的矩形定义-并将这些值设置为已知数字。最终,我想要类似下图(右)所示的图像。
我没有程序包的偏好设置,但是我一直在查看Images,OpenCV等。我希望有一种直接的方法来实现此目的。
解决方法
我想识别特定的像素-由具有长度,宽度和旋转度的矩形定义
仅知道长度,宽度和旋转度不足以在平面上唯一定位矩形。您还需要翻译。
这是一个简单的代码,为您提供了一个示例,您可以执行此操作(效率不是很高,但足够快用于演示目的):
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)
在其中-与传递旋转,缩放和平移相比,我认为更容易假设您传递矩形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,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循环在填充栅格化方面效率不高。从卢克索访问像素数据可能会更好,或者使用其他将仿射变换应用于矩阵的函数。
关于朱莉娅阴谋的警告:
第一次绘图的时间很慢。为了对其进行任何真正的迭代,您应该利用Revise.jl
并将测试功能保存在文件中,并将其包含在includet("test.jl")
中。然后,您的julia会话将持续进行,您只需等待一次using
语句即可。