Способы преобразования записи из файла .csv обратно в фигуру

#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. Большое вам спасибо! Я решил использовать только метод перекрестных ссылок.