У меня типичная путаница в синтаксисе копирования и вставки, вероятно, потому, что я действительно не понимаю, что делаю!
Я пытаюсь сохранить ряд координат facemark_landmark, взятых из библиотеки mediapipe. Я перебираю кадры фильма, и каждый кадр дает мне 468 целочисленных пар, экранных координат каждого ориентира.
В каждом кадре я добавляю список координат в список с именем Stored_Data.
stored_data.append(landmark_coords)
Когда фильм закончен, я записываю данные в файл:
with open("out.csv", "w") as f:
wr = csv.writer(f)
wr.writerows(stored_data)
Кажется, это работает нормально, и мой CSV-файл выглядит так: (181, 95), (170, 87), ..... 468 пар в каждой строке, по одной строке на каждый кадр фильма.
Но я запутался, пытаясь преобразовать файл csv обратно в правильный формат.
Мои текущие усилия:
stored_data = []
with open("out.csv", "r") as f:
rr = csv.reader(f)
for row in rr:
frland=[]
for l in row:
coords = [map(float,l.split(',')) for i in l]
frland.append(coords)
stored_data.append(frland)
Я получаю сообщение об ошибке: ValueError: установка элемента массива с помощью последовательности. Запрошенный массив имеет неоднородную форму после 1 измерения. Обнаруженная форма была (468,) + неоднородная часть.
Может ли кто-нибудь дать мне руку?
Спасибо, это, безусловно, намного лучше подходит для моей проблемы.






CSV, по моему опыту, предназначен для обмена данными между разными людьми и процессами. CSV не имеет нативных типов как таковых, все сериализуется как строка, но да, теперь у вас возникают проблемы с расшифровка некоторыми значениями, когда вы пытаетесь прочитать их обратно.
И поскольку вам нужно декодировать, это хороший показатель того, что что-то другое может быть лучше, чем CSV. Если вам просто нужно сохранить результаты mediapipe между процессами, я повторю то, что Ари сказал в комментариях, используйте pickle: он там для хранения сложных типов, поэтому вам не нужно думать о кодировании и декодировании и сделать его таким простым, как «сохранить, затем откройте":
import pickle
orig_stored_data = [[(181, 95), (170, 87)], [(20, 40), (30, 50)]]
f_pickle = open("stored_data.pkl", "wb")
pickle.dump(orig_stored_data, f_pickle)
f_pickle = open("stored_data.pkl", "rb")
new_stored_data = pickle.load(f_pickle)
assert new_stored_data == orig_stored_data
Если вам нужно использовать CSV, вам нужно правильно интерпретировать кортежи в каждом столбце. Я думаю, что это неполный:
coords = [map(float,l.split(',')) for i in l]
поскольку вы не удаляете скобки перед разделением запятой.
Более простой подход — использовать функцию literal_eval() в модуле ast:
import ast, csv, io, pprint
f_in = io.StringIO('"(181, 95)","(170, 87)"\n"( 20, 40)","(30,50)"')
stored_data = []
reader = csv.reader(f_in)
for row in reader:
frland = []
for col in row:
coords = ast.literal_eval(col)
frland.append(coords)
stored_data.append(frland)
и stored_data выглядит так:
[[(181, 95), (170, 87)],
[(20, 40), (30, 50)]]
Да, я думаю, что Ари был прав, на этот раз рассол выручит меня из рассолов! Мне не нужно увязнуть в ненужном преобразовании в формат csv и из него. Спасибо за ваш подробный ответ.
Есть ли причина, по которой вы хотите, чтобы файл был удобочитаемым CSV? Если вы просто ищете очень простое сохранение объектов Python, то это именно то, для чего предназначен
pickle? :)