#python #pandas #image #csv #figure
#python #pandas #изображение #csv #рисунок
Вопрос:
Я пытаюсь сохранить информацию о фигуре в файл .csv, используя изображение, но я застрял при преобразовании его обратно в фигуру. Он продолжает выдавать мне ошибку «AttributeError: объект ‘str’ не имеет атрибута’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(), он не работает.
Большое вам спасибо!
Комментарии:
1. Как именно вы сохранили свое изображение в csv? Ваш код должен показывать это для воспроизведения.
2. CSV не является родным способом сохранения изображений. Данные, вероятно, искажены.
3. @BillHuang Я добавил код, пожалуйста, взгляните. Я сохраняю и конвертирую только эту конкретную запись.
4. @gtomer Hmmm…do вы думаете, что если я сохраню матрицу ошибок в файле csv, извлеку ее и нанесу на график впоследствии, возможно, это будет альтернативный способ? Или, может быть, просто создайте столбец с именем фигуры и отдельную папку, содержащую все цифры, чтобы я мог делать перекрестные ссылки?
Ответ №1:
Прежде всего, если возможно, НЕ ДЕЛАЙТЕ ЭТОГО. Это слишком дорого. Просто создайте таблицу (фрейм данных), записывающую метки, связанные с каждым файлом, которые можно запросить позже. Например.
| file_id | file_path | label |
|---------|-----------|-----------|
| 1 | a.jpg | fine-arts |
| 2 | b.png | manga |
| 3 | c.jpb | whatever |
Если вам ДЕЙСТВИТЕЛЬНО нужно кодировать изображения в строки, кодирование base64 является распространенным способом. Например, jupyter notebook
использует base64
формат для встраивания изображений в HTML-файл, чтобы пользователи могли легко делиться полученными изображениями.
Во-вторых, по-прежнему НЕ рекомендуется сохранять пару (метка, данные) в виде файла csv из-за ограничения ширины столбца для программного обеспечения для работы с электронными таблицами. И если нельзя воспользоваться преимуществами .csv
format, зачем его использовать? Поэтому в этом случае все же лучше создать таблицу поиска, упомянутую выше, чтобы избежать ненужного дорогостоящего преобразования.
Если вы все еще делаете это, хорошо, вот пример кода. МАЛЕНЬКОЕ изображение взято с домашней страницы debian. Можно проверить, что данные правильно восстановлены.
Код:
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()
Однако, если используется изображение большего размера, например, Мона Лиза, программа чтения csv будет жаловаться:
_csv.Error: field larger than field limit (131072)
И вам все еще нужна форма изображения, чтобы восстановить размеры. Поэтому на самом деле необходим третий столбец, хранящий форму изображения.
Комментарии:
1. Большое вам спасибо! Я решил использовать только метод перекрестных ссылок.