Esta página apresenta as principais soluções apresentadas no programa Rampa. O objetivo é entender as discrepâncias entre elas e comparar suas vantagens e desvantagens.
Nesta abordagem, a matriz das coordenadas das colunas "c" já é a rampa desejada. O único cuidado é que como um dos valores de teste a rampa ultrapassa o valor 255, é importante que o tipo de pixel seja inteiro com no mínimo 16 bits.
In [19]:
def rr_indices( lado):
import numpy as np
r,c = np.indices( (lado, lado), dtype='uint16' )
return c
print(rr_indices(11))
Existem no mínimo três soluções que se classificam como as mais eficientes. Todas elas tem o custo de escrever uma linha e depois copiar esta linha em todas as linhas da imagem de saída.
A mais interessante e mais eficiente é a cópia por broadcast (assunto do módulo 3). Nesta solução declara-se a imagem final com empty e depois copia-se uma linha criada pelo arange para cada linha da imagem utilizando-se da propriedade de broadcast do numpy.
In [20]:
def rr_broadcast( lado):
import numpy as np
row = np.arange(lado, dtype='uint16')
g = np.empty ( (lado,lado), dtype='uint16')
g[:,:] = row
return g
print(rr_broadcast(11))
In [21]:
def rr_tile( lado):
import numpy as np
f = np.arange(lado, dtype='uint16')
return np.tile( f, (lado,1))
print(rr_tile(11))
In [22]:
def rr_resize( lado):
import numpy as np
f = np.arange(lado, dtype='uint16')
return np.resize(f, (lado,lado))
print(rr_resize(11))
O repeat to numpy repete cada pixel n vezes. Para utilizá-lo no neste problema, repetindo-se a linha rampa (arange) por lado, depois de reformatá-lo para duas dimensões há necessidade de fazer a transposição pois a repetição se dá na horizontal e o que se quer é a repetição na veritical, pois na imagem final as linhas são repetidas.
In [23]:
def rr_repeat( lado):
import numpy as np
f = np.arange(lado, dtype='uint16')
return np.repeat( f, lado).reshape(lado, lado).transpose()
print(rr_repeat(11))
Uma solução que não foi encontrada é a que utiliza o operador "módulo", isto é, o resto da divisão. Nesta solução, cria-se um vetor único do tamanho final da imagem, aplicando-se o operador "modulo lado". Depois basta reformatar para duas dimensões. O inconveniente desta solução é que o vetor precisa ser de 32 bits, pois o número total de pixels normalmente é maior que 65535, que é o máximo que se pode representar em 'uint16'.
In [24]:
def rr_modulo( lado):
import numpy as np
f = np.arange(lado * lado, dtype='int32')
return (f % lado).reshape(lado,lado)
print(rr_modulo(11))
In [25]:
p = [rr_broadcast, rr_resize, rr_repeat, rr_tile, rr_indices, rr_modulo]
lado = 101
f = rr_indices(lado)
for func in p:
if not (func(lado) == f).all():
print('func %s failed' % func.__name__)
In [26]:
import numpy as np
p = [rr_broadcast, rr_tile, rr_resize, rr_repeat, rr_modulo, rr_indices]
lado = 20057
for func in p:
print(func.__name__)
%timeit f = func(lado)
print()
In [ ]: