Считать строковое представление массива 2D из столбца CSV в массив 2D numpy - PullRequest
0 голосов
/ 07 января 2020

У меня есть pandas кадр данных, для которого один из столбцов содержит массивы 2D numpy, соответствующие пиксельным данным из изображений в градациях серого. Эти 2D numpy массивы имеют форму (480, 640) или (490, 640). Фрейм данных имеет другие столбцы, содержащие другую информацию. Затем я генерирую из него файл csv с помощью функции pandas 'to_csv(). Теперь моя проблема: все мои 2D numpy массивы отображаются как строки в моем CSV, так как я могу прочитать их обратно и снова преобразовать в 2D numpy массивы?

I Я знаю, что в StackOverflow есть похожие вопросы, но я не смог найти ни одного, который бы действительно фокусировался на 2D numpy массивах. Похоже, они в основном состоят из массивов 1D numpy, и представленные решения не работают.

Любая помощь очень ценится.

ОБНОВЛЕНИЕ:

В соответствии с просьбой, я добавляю некоторый код ниже, чтобы прояснить, в чем заключается моя проблема.

# Function to switch images to grayscale format
grayscale(img):
  cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Iterating through my dataframe (called data), reading all image files, making them grayscale and then adding them to my collection.
grayscale_images = []
for index, row in data.iterrows():
  img_path = row['Image path']
  cv_image = cv2.imread(img_path)
  gray = grayscale(cv_image)
  grayscale_images.append(gray)

# Make numpy array elements show without truncation
np.set_printoptions(threshold=sys.maxsize)

# Adding a new column to the dataframe containing each image's numpy array corresponding to pixels
data['Image data'] = grayscale_images

Поэтому, когда я закончу делать это и другие операции над другими столбцами, я экспортирую свой фрейм данных в CSV вот так:

data.to_csv('new_dataset.csv', index=False)

В другой записной книжке Jupyter я пытаюсь прочитать свой CSV-файл и затем извлечь массивы numpy моего изображения, чтобы передать их в сверточную нейронную сеть в качестве входных данных, как часть контролируемого training.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import sys
import re

data = pd.read_csv('new_dataset.csv')
# data.head() -- It looks fine here

# Config to make numpy arrays display in their entirety without truncation
np.set_printoptions(threshold=sys.maxsize)

# Checking if I can extract a 2D numpy array for conversion from a cell.
# That's where I notice it's a string, and I'm having trouble turning it back to a 2D numpy array
image_arr = data.iloc[0,0]

Но я застрял, преобразуя свое строковое представление из моего файла CSV в массив 2D numpy, особенно тот, который имеет форму (490, 640), как это было до экспорта кадр данных в CSV.

Ответы [ 3 ]

1 голос
/ 07 января 2020

Построить CSV со строками массива:

In [385]: arr = np.empty(1, object)                                             
In [386]: arr[0]=np.arange(12).reshape(3,4)                                     
In [387]: S = pd.Series(arr,name='x')                                           
In [388]: S                                                                     
Out[388]: 
0    [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
Name: x, dtype: object
In [389]: S.to_csv('series.csv')                                                
/usr/local/bin/ipython3:1: FutureWarning: The signature of `Series.to_csv` was aligned to that of `DataFrame.to_csv`, and argument 'header' will change its default value from False to True: please pass an explicit value to suppress this warning.
  #!/usr/bin/python3
In [390]: cat series.csv                                                        
0,"[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]"

загрузить его:

In [391]: df = pd.read_csv('series.csv',header=None)                            
In [392]: df                                                                    
Out[392]: 
   0                                                1
0  0  [[ 0  1  2  3]\n [ 4  5  6  7]\n [ 8  9 10 11]]

In [394]: astr=df[1][0]                                                         
In [395]: astr                                                                  
Out[395]: '[[ 0  1  2  3]\n [ 4  5  6  7]\n [ 8  9 10 11]]'

разобрать строковое представление массива:

In [396]: astr.split('\n')                                                      
Out[396]: ['[[ 0  1  2  3]', ' [ 4  5  6  7]', ' [ 8  9 10 11]]']

In [398]: astr.replace('[','').replace(']','').split('\n')                      
Out[398]: [' 0  1  2  3', '  4  5  6  7', '  8  9 10 11']
In [399]: [i.split() for i in _]                                                
Out[399]: [['0', '1', '2', '3'], ['4', '5', '6', '7'], ['8', '9', '10', '11']]
In [400]: np.array(_, int)                                                      
Out[400]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

Нет гарантии что это самый красивый и чистый анализ, но он дает представление о работе, которую вы должны сделать. Я заново изобретаю колесо, но поиск дубликата занял слишком много времени.

Если возможно, попытайтесь избежать сохранения такого кадра данных, как csv. Формат CSV предназначен для чистой 2-мерной таблицы, простых непротиворечивых столбцов, разделенных разделителем.

И по большей части избегайте подобных фреймов / серий. Серия может иметь объект dtype. И каждый элемент объекта может быть сложным, например, список, словарь или массив. Но я не думаю, что pandas имеет специальные функции для обработки этих случаев.

numpy также имеет dtypes объекта (как мой arr), но список часто так же хорош, если не лучше , Построить такой массив может быть сложно. Математика на таком массиве является хитом или мисс. Итерация в массиве объектов медленнее, чем итерация в списке.

===

re также может работать. Например, заменить пробел запятой:

In [408]: re.sub('\s+',',',astr)                                                
Out[408]: '[[,0,1,2,3],[,4,5,6,7],[,8,9,10,11]]'

Все еще не совсем верно. Есть ведущие запятые, которые душат eval.

0 голосов
/ 07 января 2020

Добавьте два столбца к фрейму данных data: изображение в градациях серого для преобразования в байты с использованием np.tostring() и исходную форму.

grayscale_images = []
grayscale_shapes = []

for index, row in data.iterrows():
  img_path = row['Image path']
  cv_image = cv2.imread(img_path)
  gray = grayscale(cv_image)
  grayscale_images.append(gray.tostring())
  grayscale_shapes.append(gray.shape)

Считайте CSV, затем восстановите массив 2d np, используя ' np.fromstring () `и сбросьте правильную форму.

  imagedata = np.fromstring(df.loc(...))   # index the image cell
  imagedata.shape = df.loc(...)            # index the corresponding shape
0 голосов
/ 07 января 2020

data = pd.read_csv ('new_dataset.csv')

Method1: data.values ​​

Method2: data.to_ numpy ()

Если данные .shape это 2D DataFrame, тогда два вышеупомянутых метода дадут ваш массив 2D numpy. Попробуйте!


Вот демонстрация:

df = pd.DataFrame(data={"A": [np.random.randn(480, 640), np.random.randn(490, 640)], "B": np.arange(5, 7)})

print(type(df.to_numpy()[0, 0]))  # <class 'numpy.ndarray'>
print(df.to_numpy()[0, 0].shape)  # (480, 640)

print(type(df.to_numpy()[1, 0]))  # <class 'numpy.ndarray'>
print(df.to_numpy()[1, 0].shape)  # (490, 640)

Я собираюсь поработать некоторое время, вы можете сначала попробовать и снова спросить, есть ли у вас какие-либо вопросы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...