将条目从 .csv 文件转换回图形的方法
Ways to convert an entry from a .csv file back to a figure
我正在尝试使用图像将图形信息保存到 .csv 文件,但我无法将其转换回图形。它一直给我错误“AttributeError:'str' object has no attribute 'array_interface'”。
我想这意味着我从 .csv 文件中提取的条目是一个字符串,需要转换为数组?
我将图形转换为 np 数组的代码如下所示:
from PIL import Image
img = np.array(Image.open(fig_file))
file_name = 'data.csv'
row_contents = [labels, img]
from csv import writer
def append_list_as_row(file_name, list_of_elem):
# Open file in append mode
with open(file_name, 'a+', newline='') as write_obj:
# Create a writer object from csv module
csv_writer = writer(write_obj)
# Add contents of list as last row in the csv file
csv_writer.writerow(list_of_elem)
append_list_as_row(file_name, row_contents)
有问题的部分(将其转换回图形)如下所示:
import pandas as pd
df1 = pd.read_csv(file_name)
fig_array = df1.loc[1, "img"]
img = Image.fromarray(fig_array, 'RGB')
img.save('test.png')
图像行导致错误。也许我不应该使用 pandas 来定位条目?对修改有什么想法吗?我试过.to_numpy(),没用。
非常感谢!
首先,如果可能的话,不要这样做。这太昂贵了。只需制作一个 table (数据框)记录与每个文件关联的标签,以后可以查询。例如
| file_id | file_path | label |
|---------|-----------|-----------|
| 1 | a.jpg | fine-arts |
| 2 | b.png | manga |
| 3 | c.jpb | whatever |
如果您真的必须将图像编码为字符串,base64 encoding 是一种常见的方法。例如,jupyter notebook
使用 base64
格式将图像嵌入到 html 文件中,以便用户可以轻松共享生成的图像。
其次,由于电子表格软件的列宽限制,仍然不建议将(标签,数据)对保存为csv文件。如果不能利用 .csv
格式,为什么要使用它?所以,这种情况下,还是做一个上面提到的查找table比较好,避免不必要的代价高昂的转换。
如果你还在做,OK,这里是示例代码。小 image is taken from debian homepage。可以验证数据是否正确恢复。
代码:
import numpy as np
from PIL import Image
import base64
import csv
# https://www.debian.org/Pics/openlogo-50.png
img_path = "/mnt/ramdisk/debian-openlogo-50.png"
img = np.array(Image.open(img_path))
img_encoded = base64.b64encode(img).decode("ascii")
label = "fine-arts"
# Simulate multiple records
data = [
[label, img_encoded],
[label, img_encoded],
[label, img_encoded]
]
# save
with open("/mnt/ramdisk/sav.csv", "w+") as f:
w = csv.writer(f)
w.writerows(data)
# load
data_loaded = []
with open("/mnt/ramdisk/sav.csv") as f:
r = csv.reader(f)
for row in r:
data_loaded.append(row)
# check data are unchanged after S/L
for i in range(3):
for j in range(2):
assert data[i][j] == data_loaded[i][j]
# decode the image (still need shape info)
r = base64.b64decode(data_loaded[0][1].encode("ascii"))
img_decoded = np.frombuffer(r, dtype=np.uint8).reshape((61, 50, 4))
# check image is restored correctly
import matplotlib.pyplot as plt
plt.imshow(img_decoded)
plt.show()
但是,如果使用较大的图像,例如 Mona Lisa,csv reader 会报错:
_csv.Error: field larger than field limit (131072)
而且你还需要图像形状来恢复尺寸。因此实际上需要第三列存储图像形状。
我正在尝试使用图像将图形信息保存到 .csv 文件,但我无法将其转换回图形。它一直给我错误“AttributeError:'str' object has no attribute 'array_interface'”。
我想这意味着我从 .csv 文件中提取的条目是一个字符串,需要转换为数组?
我将图形转换为 np 数组的代码如下所示:
from PIL import Image
img = np.array(Image.open(fig_file))
file_name = 'data.csv'
row_contents = [labels, img]
from csv import writer
def append_list_as_row(file_name, list_of_elem):
# Open file in append mode
with open(file_name, 'a+', newline='') as write_obj:
# Create a writer object from csv module
csv_writer = writer(write_obj)
# Add contents of list as last row in the csv file
csv_writer.writerow(list_of_elem)
append_list_as_row(file_name, row_contents)
有问题的部分(将其转换回图形)如下所示:
import pandas as pd
df1 = pd.read_csv(file_name)
fig_array = df1.loc[1, "img"]
img = Image.fromarray(fig_array, 'RGB')
img.save('test.png')
图像行导致错误。也许我不应该使用 pandas 来定位条目?对修改有什么想法吗?我试过.to_numpy(),没用。
非常感谢!
首先,如果可能的话,不要这样做。这太昂贵了。只需制作一个 table (数据框)记录与每个文件关联的标签,以后可以查询。例如
| file_id | file_path | label |
|---------|-----------|-----------|
| 1 | a.jpg | fine-arts |
| 2 | b.png | manga |
| 3 | c.jpb | whatever |
如果您真的必须将图像编码为字符串,base64 encoding 是一种常见的方法。例如,jupyter notebook
使用 base64
格式将图像嵌入到 html 文件中,以便用户可以轻松共享生成的图像。
其次,由于电子表格软件的列宽限制,仍然不建议将(标签,数据)对保存为csv文件。如果不能利用 .csv
格式,为什么要使用它?所以,这种情况下,还是做一个上面提到的查找table比较好,避免不必要的代价高昂的转换。
如果你还在做,OK,这里是示例代码。小 image is taken from debian homepage。可以验证数据是否正确恢复。
代码:
import numpy as np
from PIL import Image
import base64
import csv
# https://www.debian.org/Pics/openlogo-50.png
img_path = "/mnt/ramdisk/debian-openlogo-50.png"
img = np.array(Image.open(img_path))
img_encoded = base64.b64encode(img).decode("ascii")
label = "fine-arts"
# Simulate multiple records
data = [
[label, img_encoded],
[label, img_encoded],
[label, img_encoded]
]
# save
with open("/mnt/ramdisk/sav.csv", "w+") as f:
w = csv.writer(f)
w.writerows(data)
# load
data_loaded = []
with open("/mnt/ramdisk/sav.csv") as f:
r = csv.reader(f)
for row in r:
data_loaded.append(row)
# check data are unchanged after S/L
for i in range(3):
for j in range(2):
assert data[i][j] == data_loaded[i][j]
# decode the image (still need shape info)
r = base64.b64decode(data_loaded[0][1].encode("ascii"))
img_decoded = np.frombuffer(r, dtype=np.uint8).reshape((61, 50, 4))
# check image is restored correctly
import matplotlib.pyplot as plt
plt.imshow(img_decoded)
plt.show()
但是,如果使用较大的图像,例如 Mona Lisa,csv reader 会报错:
_csv.Error: field larger than field limit (131072)
而且你还需要图像形状来恢复尺寸。因此实际上需要第三列存储图像形状。