2015-02-23 3 views
2

Я хочу скопировать один массив в другой с другим размером. Я хотел бы такую ​​функцию:numpy blit (копировать часть массива на другой с другим размером)

blit(destimg,src,dstlocation) 

, например blit(zeros((7,7)),ones((3,3)),(4,4))

приведет к

array([[ 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 1., 1., 1.], 
     [ 0., 0., 0., 0., 1., 1., 1.], 
     [ 0., 0., 0., 0., 1., 1., 1.]]) 

Верхний левый центр массива src теперь в месте (4,4) массива destimg ,

если бы я сделал blit(zeros((7,7)),ones((3,3)),(5,5)) я хотел бы получить:

array([[ 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0., 1., 1.], 
     [ 0., 0., 0., 0., 0., 1., 1.]]) 

Массив src не вписывается в destimg, но его левый верхний угол все еще находится в правильном положении.

+1

Не можете вы добиться того, что вы хотите с помощью простого присваивания (т.е. '' = оператор) и с использованием правильной индексации? –

+0

@ Jan-PhilipGehrcke Я могу, но для случаев, когда массив src не подходит, я должен был бы сделать некоторые вычисления, чтобы выяснить правильную индексацию. Мне было интересно, есть ли у numpy уже функция для этого. –

+0

Почему ваша функция '' 'blit''' не достаточна? – wwii

ответ

3

Вы можете просто вычислить соответствующие ломтиков:

import numpy as np 

def blit(dest, src, loc): 
    pos = [i if i >= 0 else None for i in loc] 
    neg = [-i if i < 0 else None for i in loc] 
    target = dest[[slice(i,None) for i in pos]] 
    src = src[[slice(i, j) for i,j in zip(neg, target.shape)]] 
    target[[slice(None, i) for i in src.shape]] = src 
    return dest 

print(blit(np.zeros((7,7)), np.ones((3,3)), (5, 5))) 

урожаи

[[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 1. 1.] 
[ 0. 0. 0. 0. 0. 1. 1.]] 

и

print(blit(np.zeros((7,7)), np.ones((3,3)), (-1, -1))) 

Урожайность

[[ 1. 1. 0. 0. 0. 0. 0.] 
[ 1. 1. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.]] 
0

Мне удалось найти решение (немного подробный), должен быть более элегантный способ, но в середине времени это будет делать.

from numpy import * 

def blit(dest, src, loc): 
    th,tw=dest.shape 
    sh,sw=src.shape 
    sr = 0 if -loc[0]<0 else -loc[0] 
    fr = sh if loc[0]+sh<=th else sh-(loc[0]+sh-th) 
    sc = 0 if -loc[1]<0 else -loc[1] 
    fc = sw if loc[1]+sw<=tw else sw-(loc[1]+sw-th) 
    loc[0] = max(0,loc[0]) 
    loc[1] = max(0,loc[1]) 
    dest[loc[0]:loc[0]+sh-sr,loc[1]:loc[1]+sw-sc] = src[sr:fr,sc:fc] 

dest = zeros((7,7)) 
src = ones((3,3)) 
loc = [5,5] 
blit(dest, src, loc) 
print dest 

выходы:

[[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 1. 1.] 
[ 0. 0. 0. 0. 0. 1. 1.]] 

и

dest = zeros((7,7)) 
src = ones((3,3)) 
loc = [-1,-1] 
blit(dest, src, loc) 
print dest 

дает

[[ 1. 1. 0. 0. 0. 0. 0.] 
[ 1. 1. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0.]] 
+0

Как вы видите, лучший способ - это то, что придумал @unutbu. Вы должны определенно использовать тот факт, что нарезанная индексация на массивах numpy ведет себя как срез Python во встроенных типах по отношению к индексам без привязки. Цитата из введения Python к строкам: «Дегенерированные индексы среза обрабатываются изящно: слишком большой индекс заменяется размером строки, верхняя граница меньше нижней границы возвращает пустую строку». –

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