如何将文件中的 csv 值存储到 Python 中的 numpy 数组?
How to store csv values form a file to a numpy array in Python?
我写了一个 Python 脚本,它读取黑白位图图像并将每个像素的值存储为 .txt 文件中从 0x00 到 0xFF 的十六进制值。这些值存储为以逗号分隔的连续一维数组,为了不让文件太宽,行是 仅 最大为 16长度元素,例如:
v01, v02, ... , v15, v16,
v17, v18, ... , v31, v32,
...
0x00, 0x00, ... , 0x00, 0x00,
0x00, 0x00, ... , 0x00, 0x00,
...
注意每一行的最后一个元素也有一个逗号
当然 .txt 文件不保留位图的原始尺寸,但这不是问题,因为它稍后会在知道原始尺寸并处理的微控制器固件中使用正确读取一维数组。
现在,为了验证转换是否正确完成,我需要编写一个脚本来读取文件并将值存储在一个 numpy 数组中,该数组用于稍后使用 "matplotlib" 显示图像.
我试过以下代码:
my_data = genfromtxt('file.txt', delimiter=',')
print(my_data)
问题是,除了错误的尺寸外,十六进制值没有被读取为数字,而且行的最后一个逗号之后的元素也被读取(我猜是中断字符)。我得到类似的东西:
[nan, nan, ... , nan, nan," "
...]
我需要一种读取 .txt 文件的方法,将值从“0x00”格式转换为数值,然后存储在 m x n numpy 数组中(m & n 是已知参数,原始位图大小):
[[0, 0, ... , 0, 0]
[0, 0, ... , 0, 0]
...]
有什么建议吗?
更新
在写这个问题时,我只处理宽度为 16 像素倍数的文件,这保证了我的 csv 输出在所有行中始终有 16 个元素。但经过一些测试后,我遇到了一张图片,其大小使 csv 的最后一行少于 16 个元素。在那种情况下,我无法使用@taras 提供的解决方案,但根据我最初的问题,答案仍然是正确的。
最后我得到了以下代码,可能不那么优雅,但确实有效:
with open(filename,"r") as f:
pixels=[x.split(',') for x in f.readlines()]
for p in pixels:
del p[-1]
pixels = [int(p,16) for row in pixels for p in row]
pixels = np.asarray(pixels, dtype=np.uint8).reshape(h,w)
我会保留这两个答案,以防有人觉得它们有用。
因为你有固定数量的列,你可以使用它来只读取前 16 列(它会让你去掉尾随的逗号)并使用 converters
dict 将每一列从十六进制转换int(x, 16)
:
import numpy as np
fname = 'file.txt'
num_cols = 16
np.loadtxt(fname, usecols=range(num_cols), dtype=np.uint8, delimiter=',',
converters={k: lambda x: int(x, 16) for k in range(num_cols)})
编辑:
如果文件中的元素个数不是16的倍数,可以使用正则python代码对数据进行预处理,然后转成numpy数组:
import numpy as np
fname = 'file.txt'
with open(fname) as fp:
data = fp.read().replace('\n', '')
np.array([int(x, 16) for x in data.split(',')])
我写了一个 Python 脚本,它读取黑白位图图像并将每个像素的值存储为 .txt 文件中从 0x00 到 0xFF 的十六进制值。这些值存储为以逗号分隔的连续一维数组,为了不让文件太宽,行是 仅 最大为 16长度元素,例如:
v01, v02, ... , v15, v16,
v17, v18, ... , v31, v32,
...
0x00, 0x00, ... , 0x00, 0x00,
0x00, 0x00, ... , 0x00, 0x00,
...
注意每一行的最后一个元素也有一个逗号
当然 .txt 文件不保留位图的原始尺寸,但这不是问题,因为它稍后会在知道原始尺寸并处理的微控制器固件中使用正确读取一维数组。
现在,为了验证转换是否正确完成,我需要编写一个脚本来读取文件并将值存储在一个 numpy 数组中,该数组用于稍后使用 "matplotlib" 显示图像. 我试过以下代码:
my_data = genfromtxt('file.txt', delimiter=',')
print(my_data)
问题是,除了错误的尺寸外,十六进制值没有被读取为数字,而且行的最后一个逗号之后的元素也被读取(我猜是中断字符)。我得到类似的东西:
[nan, nan, ... , nan, nan," "
...]
我需要一种读取 .txt 文件的方法,将值从“0x00”格式转换为数值,然后存储在 m x n numpy 数组中(m & n 是已知参数,原始位图大小):
[[0, 0, ... , 0, 0]
[0, 0, ... , 0, 0]
...]
有什么建议吗?
更新
在写这个问题时,我只处理宽度为 16 像素倍数的文件,这保证了我的 csv 输出在所有行中始终有 16 个元素。但经过一些测试后,我遇到了一张图片,其大小使 csv 的最后一行少于 16 个元素。在那种情况下,我无法使用@taras 提供的解决方案,但根据我最初的问题,答案仍然是正确的。
最后我得到了以下代码,可能不那么优雅,但确实有效:
with open(filename,"r") as f:
pixels=[x.split(',') for x in f.readlines()]
for p in pixels:
del p[-1]
pixels = [int(p,16) for row in pixels for p in row]
pixels = np.asarray(pixels, dtype=np.uint8).reshape(h,w)
我会保留这两个答案,以防有人觉得它们有用。
因为你有固定数量的列,你可以使用它来只读取前 16 列(它会让你去掉尾随的逗号)并使用 converters
dict 将每一列从十六进制转换int(x, 16)
:
import numpy as np
fname = 'file.txt'
num_cols = 16
np.loadtxt(fname, usecols=range(num_cols), dtype=np.uint8, delimiter=',',
converters={k: lambda x: int(x, 16) for k in range(num_cols)})
编辑:
如果文件中的元素个数不是16的倍数,可以使用正则python代码对数据进行预处理,然后转成numpy数组:
import numpy as np
fname = 'file.txt'
with open(fname) as fp:
data = fp.read().replace('\n', '')
np.array([int(x, 16) for x in data.split(',')])