У меня проблема. Проблема в том, что я хочу создать подкласс массива numpy, а затем создать массив объектов этого типа. Когда я ссылаюсь на элемент в этом массиве, я хочу, чтобы он по-прежнему был экземпляром этого подкласса. Вместо этого это экземпляр массива numpy.
Вот тест, который не проходит:
import numpy as np
class ImageWrapper(np.ndarray):
def __new__(cls, image_data):
assert image_data.ndim in (2, 3)
return image_data.view(cls)
@property
def n_colours(self):
return 1 if self.ndim==2 else self.shape[2]
n_frames = 10
frames = [ImageWrapper(np.random.randint(255, size = (20, 15, 3)).astype('uint8')) for _ in xrange(n_frames)]
video = np.array(frames)
assert video[0].n_colours == 3
Дает мне: AttributeError: объект 'numpy.ndarray' не имеет атрибута 'n_colours'
Как я могу заставить это работать?
Вещи, которые уже пробовали:
- Установка subok=True при построении видео — это работает только при построении массива из одного экземпляра объекта подкласса, а не списка.
- Установка dtype=object или dtype=ImageWrapper не работает
Я понимаю, что могу просто сделать видео списком, но было бы предпочтительнее сохранить его в виде массива numpy по другим причинам.
array
для списка 3D-массивов, вы получаете 4D-массив, а не 1D-массив, полный 3D-массивов. Очевидно, что массив 4D не может бытьImageWrapper
, так что этоndarray
, поэтому любой его фрагмент также являетсяndarray
, независимо от того, откуда изначально были получены данные. Вопрос в том, почему вы хотите, чтобы это был массив? 1D-массив изobject
не теряет всех преимуществ numpy по сравнению с нативными списками, но теряет много из них, и если вы можете назвать другие причины, в вашем последнем предложении это может помочь. - person abarnert   schedule 23.07.2014ImageWrapper
? Вашn_colours
должен был бы вернуть массив из N-3 измерений вместо скаляра, если N>3 (или просто вызвать исключение), но в противном случае, в чем была бы проблема? Потому что это сильно упростило бы задачу… - person abarnert   schedule 23.07.2014n_colours
иcrop
иdownsample
и так далее по этому массиву. 4D-массив дает вам все это бесплатно (по крайней мере, на стороне вызывающей стороны; вы должны быть осторожны на стороне реализации, как показывает Bi Rico); с массивом объектов, которые являются массивами, вам нужно вручную обернуть несвязанный метод вufunc
, чтобы что-то сделать. (Если вы не планируете просто перебирать объекты, в таком случае зачем использовать массив?) - person abarnert   schedule 23.07.2014