Introdução ao NumPy no ambiente Adessowiki

Redução de eixo

.. contents::

Operação combinando todos os pixels

Existem várias funções que calculam valores estatísticos da imagem, como valor máximo, valor médio, soma, entre outras, que permitem sua aplicação em todos os pixels resultando num valor escalar único.

Vejam alguns exemplos de cálculo do máximo valor do array, valor médio e somatório de todos os valores:


In [5]:
import numpy as np

a = np.arange(24).reshape((4,6))
print("a = \n", a)
print('a.max()=',  a.max())
print('a.mean()=', a.mean())
print('a.sum()=',  a.sum())


a = 
 [[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]
 [12 13 14 15 16 17]
 [18 19 20 21 22 23]]
a.max()= 23
a.mean()= 11.5
a.sum()= 276

A título de curiosidade, em processamento paralelo, fazer este tipo de operação, que acumula um único valor a partir dos valores de cada pixel é uma das operações mais ineficientes, pois existe o gargalo que todos os pixels precisam ser acumulados numa única variável. Este tipo de operação, em processamento paralelo, é denominada redução, pois você reduz todos os elementos do ndarray a um único valor.

Operação combinando eixos (redução de eixo)

É possível também fazer estas operações que combinam os pixels, apenas em alguns eixos, isto é denominado redução de eixo. Para se conseguir isto, basta utilizar como parâmetro da função usada para a combinação dos valores o eixo em que os valores serão calculados. Assim, se a imagem for bidimensional, eixos 0 (linhas) e 1 (colunas), se quisermos combinar na direção das linhas utilizamos 0 como parâmetro e se quisermos acumular na direção das colunas, utilizamos um como parâmetro. Existem vários métodos que podem ser utilizados. Vejamos os exemplos a seguir:


In [8]:
print ('a =\n',a )
print ('a.shape = ', a.shape )
print ('a.max(0) = ', a.max(0) )
print ('a.max(0).shape = ', a.max(0).shape )
print ('a.max(1) = ', a.max(1) )
print ('a.max(1).shape = ', a.max(1).shape )


a =
 [[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]
 [12 13 14 15 16 17]
 [18 19 20 21 22 23]]
a.shape =  (4, 6)
a.max(0) =  [18 19 20 21 22 23]
a.max(0).shape =  (6,)
a.max(1) =  [ 5 11 17 23]
a.max(1).shape =  (4,)

Note que a.max(0) opera no eixo das linhas, resultando o valor máximo de cada coluna. O resultado possui 4 elementos que é o número de colunas de a. Note que o shape foi reduzido de (5,4) para (4,), pois a operação se deu na dimensão 0.

Já o a.max(1) opera na direção do eixo nas colunas, resultando o máximo em cada linha. O shape reduziu de (5,4) para (5,).

Outros exemplos numéricos

A seguir outros exemplos reduzindo o eixo 0 (linhas). Em todos os exemplos a seguir, como a redução se dá no eixo 0, o vetor resultante terá shape (4,), pois o eixo 0 do shape (5,4) de a.


In [9]:
print ('a =\n',a )
print ('a.mean(0) = ', a.mean(0) )
print ('a.min(0) = ', a.min(0) )
print ('a.sum(0) = ', a.sum(0) )
print ('a.cumsum(0) = ', a.cumsum(0) ) # soma acumulada


a =
 [[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]
 [12 13 14 15 16 17]
 [18 19 20 21 22 23]]
a.mean(0) =  [  9.  10.  11.  12.  13.  14.]
a.min(0) =  [0 1 2 3 4 5]
a.sum(0) =  [36 40 44 48 52 56]
a.cumsum(0) =  [[ 0  1  2  3  4  5]
 [ 6  8 10 12 14 16]
 [18 21 24 27 30 33]
 [36 40 44 48 52 56]]

Redução no eixo com aplicações em imagens

No exemplo abaixo, calculamos o perfil médio das colunas numa imagem que representa um recorte de uma parte de uma calculadora.

O perfil médio dos pixels é calculado com a operação de mean(0) para se fazer a redução da dimensão 0 (linhas). Veja a interpretação da curva no gráfico. As teclas são escuras, porém as letras são bem claras dando um valor médio mais baixo que o fundo das teclas que possui um nível de cinza maior. Observe que mean(0) irá calcular a média de cada coluna, assim, o hmean[0] abaixo será a média de todos os pixels da primeira coluna, o hmean[1], a média de todos os pixels da segunda coluna de f e assim por diante. Veja que a operação sendo na direção das linhas (eixo 0), podemos interpretar que o resultado é uma linha horizontal média da imagem ou é uma linha onde cada elemento é a média dos pixels de cada coluna da imagem.


In [10]:
import ia636 as ia
f = adreadgray('keyb.tif')
adshow(f,'f: shape(%d,%d)' % (f.shape[0], f.shape[1]))
hmean = f.mean(0)
#adshow(ia.iaplot(hmean,ylabel='intensidade',xlabel='coluna'),'f.mean(0), valor médio de cada coluna')


---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-10-2f9a51eeac00> in <module>()
----> 1 import ia636 as ia
      2 f = adreadgray('keyb.tif')
      3 adshow(f,'f: shape(%d,%d)' % (f.shape[0], f.shape[1]))
      4 hmean = f.mean(0)
      5 adshow(ia.iaplot(hmean,ylabel='intensidade',xlabel='coluna'),'f.mean(0), valor médio de cada coluna')

ModuleNotFoundError: No module named 'ia636'

Veja o exemplo similar, mas agora calculando os valores mínimos de cada coluna.


In [13]:
#import ia636 as ia

f = adreadgray('keyb.tif')
adshow(f,'f: shape(%d,%d)' % (f.shape[0], f.shape[1]))
hmin = f.min(0)
adshow(ia.iaplot(hmin,ylabel='intensidade mínima',xlabel='coluna'),'f.min(0), valor mínimo de cada coluna')


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-13-d35ca1f18540> in <module>()
      2 #import ia636 as ia
      3 
----> 4 f = adreadgray('keyb.tif')
      5 adshow(f,'f: shape(%d,%d)' % (f.shape[0], f.shape[1]))
      6 hmin = f.min(0)

NameError: name 'adreadgray' is not defined

Tratamento com arrays de muitas dimensões

Uma das vantagens do NumPy é sua generalização para tratar arrays de quaisquer dimensões. Vamos ver alguns exemplos com 4 dimensões:


In [12]:
a = np.arange(120).reshape((2,3,4,5))
print ('a.shape:', a.shape
print ('a=\n', a


  File "<ipython-input-12-ae3c8acdca5d>", line 3
    print ('a=\n', a
        ^
SyntaxError: invalid syntax

Redução no segundo eixo (axis = 1):


In [ ]:
b = a.sum(axis=1)
print ('b.shape:', b.shape )
print ('b=\n', b )

Uma forma conveniente de indicar o eixo da redução é contá-lo do eixo menos significativo como sendo o eixo -1. Assim se usarmos eixos positivos, com 4 dimensões os eixos são: 0 (mais significativo, 1, 2 e 3 (menos significativo). Quando se usa valor negativo, s contagem passa a ser: -4 (mais significativo), -3, -2 e -1 (menos significativo).

No exemplo a seguir, é feita uma redução de eixo no menos significativo:


In [ ]:
c = a.sum(axis=-1)
print ('c.shape:',c.shape )
print ('c=\n', c )