【问题标题】:Generate image data from three numpy arrays从三个 numpy 数组生成图像数据
【发布时间】:2016-06-07 08:39:46
【问题描述】:

我有三个 numpy 数组,XYZ

XY 是空间网格的坐标,每个网格点(X, Y) 的强度为Z。我想使用此数据保存 PNG 图像。不需要插值,因为XY 保证覆盖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..
...

【问题讨论】:

  • Z的形状是什么?
  • 对不起,我问错了。所有三个数组都有维度N,并且XY 包含重复值。我将在原始问题中添加一个示例。
  • 如何管理重复值?最大,第一,是什么意思?

标签: python numpy


【解决方案1】:

首先,您应该运行这段代码:

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)

【讨论】:

  • 嗨,Z 是一维数组,就像 X 和 Y 一样。
  • 感谢您的建议。我想这会起作用,但是,我希望有一种更 pythonic 的方式来做到这一点。但在我找到合适的东西之前,我会坚持使用你的代码。
  • 如果数据量很大,可以考虑使用 Pandas 的 groupby 方法来加速这个操作:pandas.pydata.org/pandas-docs/stable/groupby.html
【解决方案2】:

你说你不需要插值,因为每个网格点都被覆盖了。所以我假设这些点是等距的。

如果您的表已经通过增加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')

如果您的输入未排序(看起来好像已排序但谁知道),您必须在开始之前对其进行排序。根据您的输入,这可能很容易,也可能很困难。

【讨论】:

  • reshape() 是我正在寻找的。完美,现在它是单行的,我可以简单地做np.unique(x).size...谢谢!
  • 我无法理解这段代码是如何工作的。 y_values 是一个元组,reshape 如何管理它???
  • 谢谢。但我认为它只有在 Z.size =x_values*y_values 时才有效,如果有重复则不保证.....
  • 从问题“每个网格点(X,Y)都有一个强度Z”“X和Y保证覆盖min( X) 和 max(Y)" 所以听起来没有重复值和缺失值。
  • 好的,可能是为了 OP。示例数据中并非如此。
【解决方案3】:

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)

【讨论】:

    猜你喜欢
    • 2020-02-08
    • 2021-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-13
    • 2017-02-04
    • 1970-01-01
    相关资源
    最近更新 更多