我有三个numpy数组,X
,Y
和Z
。
X
和Y
是空间网格的坐标,每个网格点(X, Y)
的强度为Z
。我想使用这些数据保存PNG图像。不需要插值,因为X
和Y
可以保证涵盖min(X)
和max(Y)
之间的每个网格点。
我猜测解决方案位于numpy的meshgrid()
函数中,但我无法弄清楚如何将Z
数组重塑为NxM
强度数据。
我该怎么做?
为了阐明输入数据结构,它是这样的:
X | Y | Z
-----------------------------
0.1 | 0.1 | something..
0.1 | 0.2 | something..
0.1 | 0.3 | something..
...
0.2 | 0.1 | something..
0.2 | 0.2 | something..
0.2 | 0.3 | something..
...
0.2 | 0.1 | something..
0.1 | 0.2 | something..
0.3 | 0.3 | something..
...
答案 0 :(得分:2)
首先,你应该运行这段代码:
import numpy as np
X = np.asarray(<X data>)
Y = np.asarray(<Y data>)
Z = np.asarray(<Z data>)
Xu = np.unique(X)
Yu = np.unique(Y)
然后您可以应用以下任何一种方法。值得注意的是,即使数据未被排序(与当前接受的答案形成对比),所有这些都可以正常工作:
1)for
循环和numpy.where()
函数
这可能是最简单,最易读的解决方案:
Zimg = np.zeros((Xu.size, Yu.size), np.uint8)
for i in range(X.size):
Zimg[np.where(Xu==X[i]), np.where(Yu==Y[i])] = Z[i]
2)列表理解和numpy.sort()
功能
这个解决方案 - 比前一个更复杂 - 依赖于Numpy的structured arrays:
data_type = [('x', np.float), ('y', np.float), ('z', np.uint8)]
XYZ = [(X[i], Y[i], Z[i]) for i in range(len(X))]
table = np.array(XYZ, dtype=data_type)
Zimg = np.sort(table, order=['y', 'x'])['z'].reshape(Xu.size, Yu.size)
3)矢量化
使用lexsort是执行所需任务的优雅而有效的方式:
Zimg = Z[np.lexsort((Y, X))].reshape(Xu.size, Yu.size)
4)纯Python,不使用NumPy
您可能需要查看this link以获取没有任何第三方依赖关系的纯Python解决方案。
要结束,您可以使用不同的选项将Zimg
保存为图像:
from PIL import Image
Image.fromarray(Zimg).save('z-pil.png')
import matplotlib.pyplot as plt
plt.imsave('z-matplotlib.png', Zimg)
import cv2
cv2.imwrite('z-cv2.png', Zimg)
import scipy.misc
scipy.misc.imsave('z-scipy.png', Zimg)
答案 1 :(得分:1)
你说你需要不需要插值,因为每个网格点都被覆盖了。所以我假设这些点是等距的。
如果您的表已经按照x
增加为主要排序,而y
增加了次要排序,则可以直接使用Z
数组并使用PIL
保存:
import numpy as np
# Find out what shape your final array has (if you already know just hardcode these)
x_values = np.unique(X).size
y_values = np.unique(Y).size
img = np.reshape(Z, (x_values, y_values))
# Maybe you need to cast the dtype to fulfill png restrictions
#img = img.astype(np.uint) # alter it if needed
# Print image
from PIL import Image
Image.fromarray(img).save('filename.png')
如果你的输入没有排序(它看起来像是谁知道),你必须在开始之前对其进行排序。根据您的输入,这可能很容易或非常困难。
答案 2 :(得分:0)
np.ufunc.at是以矢量化方式管理重复项的好工具。
假设这些数据:
In [3]: X,Y,Z=rand(3,10).round(1)
(array([ 0.4, 0.2, 0.1, 0.8, 0.4, 0.1, 0.5, 0.2, 0.6, 0.2]),
array([ 0.5, 0.3, 0.5, 0.9, 0.9, 0.5, 0.3, 0.6, 0.4, 0.4]),
array([ 0.4, 0.6, 0.6, 0.4, 0.1, 0.1, 0.2, 0.6, 0.9, 0.8]))
首先缩放图像(scale=3
此处):
In [4]: indices=[ (3*c).astype(int) for c in (X,Y)]
[array([1, 0, 0, 2, 1, 0, 1, 0, 1, 0]), array([1, 0, 1, 2, 2, 1, 0, 1, 1, 1])]
根据image=zeros((3,3))
界限制作一张空图片:indices
。
然后建立。在这里,我们保持最大值。
In [5]: np.maximum.at(image,indices,Z) # in place
array([[ 0.6, 0.8, 0. ],
[ 0.2, 0.9, 0.1],
[ 0. , 0. , 0.4]])
最后以PNG格式保存:matplotlib.pyplot.imsave('img.png',image)