<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 <a href="https
Step1:  Introdução ao NumPy - Redução de eixo
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 elementos do array, resultando num valor escalar único, ou aplicando apenas em algumas dimensões do array.
Quando esses métodos não tem parâmetros, a operação é aplicada em todos os eixos (reduzindo todos os eixos) resultando num valor escalar
Step2:  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
Step3:  Note que a matriz possui 2 dimensões denominados eixos 0 e 1
Step4:  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.
Step5:  Veja o exemplo similar, mas agora calculando os valores mínimos das colunas.
Step6:  Veja agora uma imagem colorida com 3 dimensões
Step7:  A imagem possui 3 dimensões
<ASSISTANT_TASK:>
Python Code:
# download image from github: -q quiet mode; -N overwrite on the next download
!wget -q -N https://github.com/robertoalotufo/ia898/raw/830a0f5f6e6a1ddd459127631bf9c0c750bf1f58/data/cameraman.tif
!wget -q -N https://github.com/robertoalotufo/ia898/raw/830a0f5f6e6a1ddd459127631bf9c0c750bf1f58/data/keyb.tif
!wget -q -N https://github.com/robertoalotufo/ia898/raw/830a0f5f6e6a1ddd459127631bf9c0c750bf1f58/figures/versicolor.jpg
!wget -q -N https://github.com/robertoalotufo/rnap/raw/master/figures/Iris_versicolor.jpg
Explanation: <a href="https://colab.research.google.com/github/robertoalotufo/ia898/blob/master/master/tutorial_numpy_1_5a.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/></a>
End of explanation
from PIL import Image
%matplotlib inline
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import numpy as np
a = np.array(Image.open('cameraman.tif'))[100:100+15,50:50+20]
print("a = \n", a)
print('a.max()=',  a.max())
print('a.mean()=', a.mean())
print('a.sum()=',  a.sum())
Explanation: Introdução ao NumPy - Redução de eixo
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 elementos do array, resultando num valor escalar único, ou aplicando apenas em algumas dimensões do array.
Quando esses métodos não tem parâmetros, a operação é aplicada em todos os eixos (reduzindo todos os eixos) resultando num valor escalar:
End of explanation
print('a =\n',a)
print('a.shape = ', a.shape)
print('a.max(axis=0) = ', a.max(0))
print('a.max(axis=0).shape = ', a.max(0).shape)
print('a.max(axis=1) = ', a.max(1))
print('a.max(axis=1).shape = ', a.max(1).shape)
Explanation: 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:
End of explanation
print('a =\n',a)
print('a.mean(axis=0) = ', a.mean(0))
print('a.min(axis=0) = ', a.min(0))
print('a.sum(axis=0) = ', a.sum(0))
Explanation: Note que a matriz possui 2 dimensões denominados eixos 0 e 1: (15,20) 15 linhas e 20 colunas. a.max(0) opera no eixo das linhas, reduzindo o eixo 0, ficando apenas o eixo 1: 20 elementos que serão os valores máximos de cada coluna. Note que o shape foi reduzido de (15,20) para (20,), pois a
operação se deu reduzindo o eixo 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 (15,20) para (15,).
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.
End of explanation
f = mpimg.imread('keyb.tif')
plt.figure(0)
plt.imshow(f,cmap='gray'); plt.title('f: shape(%d,%d)' % (f.shape[0], f.shape[1]))
hmean = f.mean(axis=0)
plt.figure(1)
plt.plot(hmean,color='r')
plt.ylabel='intensidade'
plt.xlabel='coluna'
plt.title('f.mean(0), valor médio das colunas');
Explanation: 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.
End of explanation
f = mpimg.imread('keyb.tif')
plt.figure(0)
plt.imshow(f,cmap='gray'); plt.title('f: shape(%d,%d)' % (f.shape[0], f.shape[1]))
hmin = f.min(axis=0)
plt.figure(1)
plt.plot(hmin,color='r')
plt.ylabel='intensidade'
plt.xlabel='coluna'
plt.title('f.mean(0), valor médio de cada coluna');
Explanation: Veja o exemplo similar, mas agora calculando os valores mínimos das colunas.
End of explanation
from PIL import Image
img_pil = Image.open('Iris_versicolor.jpg')
img_pil
img = np.array(img_pil)
img.shape, img.min(), img.max()
img_c = img.transpose(2,0,1)
img_c.shape
Explanation: Veja agora uma imagem colorida com 3 dimensões: altura, largura, canais:
End of explanation
# Mostrar os canais R, G, B como imagens monocromáticas individuais
# Calcular o valor médio de cada um dos canais RGB
# Calcular a imagem média dos 3 canais -> resultado é uma imagem em niveis de cinza de 2 dimensões (165,220)
# 
Explanation: A imagem possui 3 dimensões: dimensão 0: 165 linhas; dimensào 1: 220 colunas; dimensão 3: 3 canais RGB
End of explanation
<END_TASK>