2015-09-10 6 views
1

Используя numpy, скажем, у вас есть 3D-массив с именем img, заполненный значениями пикселей, и вы хотите построить массив, заполненный нулями всюду, но по заданному цветному каналу. Например, скажем, что img[0,0]=(42,84,126) в выходном массиве, выделенном для красного канала, я хотел бы иметь output_red[0,0]=(42,0,0).Numpy: Ссылка на столбец массива в другом массиве без копий

Это может быть тривиальным сделано, как это, например:

output_red=np.zeros(img.shape,dtype=img.dtype) 
output_red[...,0]=img[...,0] 

Однако я все еще пытаюсь выяснить, если есть способ сделать это:

  1. , ничего не меняя в img (в противном случае я не смогу извлечь другие цветовые каналы)
  2. без копирования данных от img до outp ut в некоторый момент.

Это можно сделать тривиально в C с помощью указателей, но поскольку numpy.ndarrays должен быть непрерывным в памяти, IMHO не надеется сделать это с помощью нарезки массива. Маски массивов не работают, так как их метод fill() копирует данные, и я должен признать, что у меня нет другой идеи.

Знаете ли вы какой-то волшебный трюк в numpy, чтобы сделать это, или это безнадежно?

Благодаря

ответ

1

Поскольку вопрос сформулирован, ответ i с.

(Если вы объясните больше о своей цели и как вы в конечном итоге используете выходной массив, мы можем предложить альтернативные решения, например, что выходной массив не должен быть массивом вообще, или что он не должен иметь такую ​​же форму, что и вход.)

Numpy ndarrays, которые собственные их данные держат структуру, которая является непрерывной в памяти, а не совместно с другими массивами которые собственных своих данных. Путь к «совместному использованию» заключается в использовании представлений (т. Е. Массивов, которые не являются собственными) (например, при разрезе), но представление относится к одному другому массиву, оно не может ссылаться на сегменты нескольких ndarrays.

В зависимости от вашего варианта использования может быть приемлемым создание большего размера ndarray, содержащего все дополнительные нули, а затем разрезать его, чтобы получить «цветные» виды, которые вы хотите.

Что-то вроде:

arr = np.array(..., shape = (N,M,3*3)) 
real_colors_arr = arr[..., :3] # all the rest are zeros 
red_arr = arr[..., 0::3] 
green_arr = arr[..., 1::3] 
blue_arr = arr[..., 2::3] 
+1

На самом деле ваша идея делает именно то, что я искал, спасибо! – user3274434

+0

'arr' в 3 раза больше, чем' img'; откуда он получает свои данные? – hpaulj

+0

@hpaulj содержит все значения NxMx3 исходного массива, объединенные нулями NxMx6 – shx2

0

Это не будет явно копия, ни делать изменения в месте, как упомянутые в двух требований, но будет использовать совершенно новый заполнитель для выхода -

output_red = np.einsum('ijk,k->ijk',img,np.array([1,0,0])) 

Sample пробег -

In [56]: img 
Out[56]: 
array([[[ 50, 83, 185], 
     [ 83, 116, 125], 
     [ 43, 179, 11]], 

     [[108, 160, 122], 
     [ 55, 206, 96], 
     [134, 149, 232]]]) 

In [57]: np.einsum('ijk,k->ijk',img,np.array([1,0,0])) 
Out[57]: 
array([[[ 50, 0, 0], 
     [ 83, 0, 0], 
     [ 43, 0, 0]], 

     [[108, 0, 0], 
     [ 55, 0, 0], 
     [134, 0, 0]]]) 
+0

Это хороший трюк, который я не знал, спасибо. – user3274434

1

@ shx2 ответ был правильным, для потомков вот как я это сделал, если кто-нибудь еще есть эта проблема один день:

# allocate a new array to store the image data and 
# get a view on each channel without copies 
# - width and height are the same as frame 
# - contains 9 entries for each pixel 
# - each entry organized like that: blue 0 0 0 green 0 0 0 red 

frame_container=np.zeros((h, w, depth*3), dtype=np.uint8) 
frame=frame_container[...,::4] 


#get a view on each channel as (b,0,0), (0,g,0), (0,0,r) 
channels={"blue":frame_container[...,:3], 
       "green":frame_container[...,3:6], 
       "red":frame_container[...,6:]} 

 Смежные вопросы

  • Нет связанных вопросов^_^