<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Table of Contents
<p><div class="lev1 toc-item"><a href="#Equalização-do-Histograma-utilizando-o-conceito-de-distribuição-uniforme-desejada" data-toc-modified-id="Equalização-do-Histograma-utilizando-o-conceito-de-distribuição-uniforme-desejada-1"><span class="toc-item-num">1&nbsp;&nbsp;</span>Equalização do Histograma utilizando o conceito de distribuição uniforme desejada</a></div><div class="lev2 toc-item"><a href="#Imagem-original" data-toc-modified-id="Imagem-original-11"><span class="toc-item-num">1.1&nbsp;&nbsp;</span>Imagem original</a></div><div class="lev2 toc-item"><a href="#Ilustração-com-caso-numérico" data-toc-modified-id="Ilustração-com-caso-numérico-12"><span class="toc-item-num">1.2&nbsp;&nbsp;</span>Ilustração com caso numérico</a></div><div class="lev2 toc-item"><a href="#Referências
Step1:  Ordena os pixels da imagem original, sabendo-se seu endereço (posição em fsi).
Isto é obtido com a função argsort. Veja como se usa o argsort
Step2:  Cria uma imagem de mesmas dimensões, porém com os pixels ordenados e com
distribuição uniforme de tons de cinza. Usamos a função linspace e
depois damos reshape na imagem para ficar bidimensional. Estes são os ladrilhos
disponíveis
Step3:  Agora temos a imagem original ordenada e os tons de cinza uniformemente
distribuídos, também ordenados
Step4:  Como sabemos o endereço original destes pixels, pois são indicados pelo
argsort feito acima, podemos agora atribuir os pixels ordenados para os
pixels ordenados da imagem uniforme.
Step5:  Pronto, o mosaico está montado e a image g está equalizada.
Step6:  Para mostrar o seu histograma e comprovar a equalização feita
Step7:  Ilustração com caso numérico
Para facilitar o entendimento, é repetido a seguir o mesmo procedimento acima, porém
com uma imagem numérica de uma dimensão com 16 pixels de valores entre 0 a 7.
Fazendo a analogia com a construção do mosaico, existem 2 pastilhas de cada tom de cinza
entre 0 a 7 para construir o mosaico com 16 pastilhas.
Calculando a imagem ordenada de f e o endereço dos pixels fsi para ordenar f
Step8:  Pastilhas disponíveis para o mosaico
Step9:  Mapeando as pastilhas no mosaico final (gs), utilizando o endereço dos pixels fsi
Step10:  Para entender como g[fsi]=gs é calculado, veja as atribuições elemento a elemento
Step11:  Imagem original e com histograma equalizado (mosaico)
Step12:  Histograma da imagem equalizada (mosaico)
<ASSISTANT_TASK:>
Python Code:
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import sys,os
ia898path = os.path.abspath('/etc/jupyterhub/ia898_1s2017/')
if ia898path not in sys.path:
    sys.path.append(ia898path)
import ia898.src as ia
f = mpimg.imread('../data/cameraman.tif')
ia.adshow(f, 'f: imagem original')
plt.plot(ia.histogram(f)),plt.title('h: histograma original');
Explanation: Table of Contents
<p><div class="lev1 toc-item"><a href="#Equalização-do-Histograma-utilizando-o-conceito-de-distribuição-uniforme-desejada" data-toc-modified-id="Equalização-do-Histograma-utilizando-o-conceito-de-distribuição-uniforme-desejada-1"><span class="toc-item-num">1&nbsp;&nbsp;</span>Equalização do Histograma utilizando o conceito de distribuição uniforme desejada</a></div><div class="lev2 toc-item"><a href="#Imagem-original" data-toc-modified-id="Imagem-original-11"><span class="toc-item-num">1.1&nbsp;&nbsp;</span>Imagem original</a></div><div class="lev2 toc-item"><a href="#Ilustração-com-caso-numérico" data-toc-modified-id="Ilustração-com-caso-numérico-12"><span class="toc-item-num">1.2&nbsp;&nbsp;</span>Ilustração com caso numérico</a></div><div class="lev2 toc-item"><a href="#Referências:" data-toc-modified-id="Referências:-13"><span class="toc-item-num">1.3&nbsp;&nbsp;</span>Referências:</a></div>
# Equalização do Histograma utilizando o conceito de distribuição uniforme desejada
Uma outra forma de equacionar o problema de equalizar a distribuição dos pixels
de uma imagem é supor que você tem um conjunto de pixels do tamanho da imagem
onde a distribuição de pixels seja uniforme.
Pensando num modelo simplificado, imagine que se deseja reproduzir
uma fotografia num mosaico construído de ladrilhos onde existe o conjunto de ladrilhos para
serem usados. Neste caso da equalização, existe um mesmo número de ladrilhos
para cada tom de cinza.
Qual é o procedimento para montar o mosaico e saber exatamente onde se coloca
cada ladrilho no mosaico? Existe uma esquema simples e intuitivo:
1. Verifica-se o tom de cinza de cada ponto na imagem e anota qual é a sua posição
   no mosaico.
2. Ordena todos os tons de cinza da fotografia.
3. Ordena todos os tons de cinza dos ladrilhos.
4. Usa o primeiro conjunto de ladrilhos mais escuros e coloca-os nas posições
   do tons de cinza mais escuros da fotografia.
5. Continua com o processo anterior até utilizar todos os ladrilhos.
Podemos fazer o mesmo procedimento de forma computacional, de forma muito mais
eficiente, porém usando o mesmo princípio.
Usamos aqui a indexação por arrays, trabalhando sempre com a indexação do
array de forma linearizada. ``f.ravel()`` é a visão da imagem de forma linearizada.
## Imagem original
End of explanation
fsi = np.argsort(f.ravel())
fs = (f.ravel()[fsi]).reshape(f.shape)
ia.adshow(fs, 'fs: imagem com pixels ordenados')
ia.adshow(ia.normalize(fsi.reshape(f.shape)),'fsi:endereço na imagem original')
Explanation: Ordena os pixels da imagem original, sabendo-se seu endereço (posição em fsi).
Isto é obtido com a função argsort. Veja como se usa o argsort: tutorial_numpy_argsort argsort.
End of explanation
gs = np.linspace(0,255,f.size).astype(np.uint8)
ia.adshow(gs.reshape(f.shape), 'gs: distribuição uniforme, pixels ordenados')
Explanation: Cria uma imagem de mesmas dimensões, porém com os pixels ordenados e com
distribuição uniforme de tons de cinza. Usamos a função linspace e
depois damos reshape na imagem para ficar bidimensional. Estes são os ladrilhos
disponíveis:
End of explanation
nb=ia.nbshow(3)
nb.nbshow(fs,'fs: imagem original pixels ordenados')
nb.nbshow(ia.normalize(fsi.reshape(f.shape)),'fsi:endereço na imagem original')
nb.nbshow(gs.reshape(f.shape),'gs: distribuição uniforme desejada, pixels ordenados')
nb.nbshow()
Explanation: Agora temos a imagem original ordenada e os tons de cinza uniformemente
distribuídos, também ordenados:
End of explanation
g = np.empty( (f.size,), np.uint8)
g[fsi] = gs
Explanation: Como sabemos o endereço original destes pixels, pois são indicados pelo
argsort feito acima, podemos agora atribuir os pixels ordenados para os
pixels ordenados da imagem uniforme.
End of explanation
ia.adshow(g.reshape(f.shape),'g[fsi] = gs, imagem equalizada')
Explanation: Pronto, o mosaico está montado e a image g está equalizada.
End of explanation
h = ia.histogram(g)
plt.bar( np.arange(h.size), h)
plt.title('histograma de g');
Explanation: Para mostrar o seu histograma e comprovar a equalização feita:
End of explanation
f = np.array([1, 7, 3, 0, 2, 2, 4, 3, 2, 0, 5, 3, 7, 7, 7, 5])
h = ia.histogram(f)
fsi = np.argsort(f)
fs = f[fsi]
print('imagem original      f  :',f)
print('indices para ordenar fsi:',fsi)
print('f c/pixels ordenados fs :',fs)
print('histogram h:          h :',h)
Explanation: Ilustração com caso numérico
Para facilitar o entendimento, é repetido a seguir o mesmo procedimento acima, porém
com uma imagem numérica de uma dimensão com 16 pixels de valores entre 0 a 7.
Fazendo a analogia com a construção do mosaico, existem 2 pastilhas de cada tom de cinza
entre 0 a 7 para construir o mosaico com 16 pastilhas.
Calculando a imagem ordenada de f e o endereço dos pixels fsi para ordenar f:
End of explanation
gs = np.linspace(0,7,f.size).round(0).astype(np.int)
print('ladrilhos ordenados, gs :', gs)
Explanation: Pastilhas disponíveis para o mosaico: 2 pastilhas de cada tom de cinza:
End of explanation
print('ladrilhos disponíveis                gs:',gs)
print('endereço para colocar cada ladrilho fsi:',fsi)
g = np.empty( (f.size,), np.uint8)
g[fsi] = gs
print('mosaico montado             g[fsi] = gs:',g)
Explanation: Mapeando as pastilhas no mosaico final (gs), utilizando o endereço dos pixels fsi:
End of explanation
print('g[fsi]= gs')
for i in np.arange(g.size):
    print('g[%d] = %d' % (fsi[i],gs[i]))
Explanation: Para entender como g[fsi]=gs é calculado, veja as atribuições elemento a elemento:
End of explanation
print('imagem usando os ladrilhos g:',g)
print('imagem original:           f:',f)
Explanation: Imagem original e com histograma equalizado (mosaico):
End of explanation
print('histograma de g:', ia.histogram(g))
Explanation: Histograma da imagem equalizada (mosaico):
End of explanation
<END_TASK>