Exercício 05 - Mapeamento de contraste ou de intensidade

Autor: Wagner Machado do Amaral
Data: 03/04/2009

Enunciado: ia636-2009:exercicio5

Índice

  • 1 - Estudo da função iaapplylut
    • 1.1 - Histograma da imagem
    • 1.2 - Função Negativo
    • 1.3 - Função Logaritmo
    • 1.4 - Função Exponencial
    • 1.5 - Função Binário
    • 1.6 - Demais Funções
  • 2 - Implementação de função semelhante a iaapplylut
  • 3 - Função interativa de melhoria de contraste da imagem
    • 3.1 - Calculando parâmetros de entrada
    • 3.2 - Obtendo a equação da reta
    • 3.3 - Montando a reta de mapeamento de contraste ou de intensidade
    • 3.4 - Utilizando a função get_reta_mapeamento para alterar o contraste da imagem.

1 - Estudo da função iaapplylut

Link para função: http://www.dca.fee.unicamp.br/ia636/ia636/iaapplylut.html

  • 1.1 - Histograma da imagem
1 imgname = 'cameraman.pgm'
2 f = iaread(imgname)
3 iashow(f,title=imgname)
4 h = iahistogram(f)
5 mmplot([[h]],['set yrange [0:'+str(h.max())+']','set xrange [0:256]'], ptitle='Histograma')

cameraman.pgm

Observe no histograma que a imagem original possui valores em toda a escala de cinza.

Porém dois picos se destacam:

O primeiro com valores entre aproximadamente 0 e 30. Esse é formado principalmente pelas cores escuras da roupa do homem

O segundo por volta de 200. Esse é formado pelas cores claras, principalmente do céu da imagem.

  • 1.2 - Função Negativo
1 it = 255 - arange(256)
2 g = iaapplylut(f, it)
3 iashow(g,title='Negativo')
4 mmplot([[it]],['set yrange [0:256]','set xrange [0:256]'], ptitle='Funcao aplicada: Negativo')
5 h = iahistogram(g)
6 mmplot([[h]],['set yrange [0:'+str(h.max())+']','set xrange [0:256]'], ptitle='Histograma')
Warning: downcasting image from int32 to uint16 (may lose precision)

Negativo

Compare o histograma da imagem transformada acima com o histograma da imagem original. Observe que a função Negativa inverteu os picos do histograma.

  • 1.3 - Função Logaritmo
1 it = log(arange(255)+1)
2 g = iaapplylut(f, it)
3 iashow(g,title='Logaritmo')
4 mmplot([[it]],['set yrange [0:10]','set xrange [0:50]'], ptitle='Funcao aplicada: Logaritmo')
5 h = iahistogram(g)
6 mmplot([[h]],['set yrange [0:'+str(h.max())+']','set xrange [0:256]'], ptitle='Histograma')
Warning: downcasting image from double to uint16 (may lose precision)

Logaritmo

  • 1.4 - Função Exponencial
1 it = arange(256)**2
2 g = iaapplylut(f, it)
3 iashow(g,title='Exponencial')
4 mmplot([[it]],['set yrange [0:50]','set xrange [0:10]'], ptitle='Funcao aplicada: Exponencial')
5 h = iahistogram(g)
6 mmplot([[h]],['set yrange [0:'+str(h.max())+']','set xrange [0:256]'], ptitle='Histograma')
Warning: downcasting image from int32 to uint16 (may lose precision)

Exponencial

  • 1.5 - Função Binário
1 it = arange(256)>100
2 g = iaapplylut(f, it)
3 iashow(g,title='Binário')
4 mmplot([[it]],['set yrange [0:256]','set xrange [0:256]'], ptitle='Funcao aplicada: Binario')
5 h = iahistogram(g)
6 mmplot([[h]],['set yrange [0:'+str(h.max())+']','set xrange [0:256]'], ptitle='Histograma')

Binário

Observe no histograma que o único valor que aparece é 1, o resto é 0 e não aparece no gráfico do histograma.

  • 1.6 - Demais Funções
1 criterio = (arange(256) <= 175) | (arange(256) >= 225)
2 it = where(criterio, arange(256), 100)
3 g = iaapplylut(f, it)
4 iashow(g,title='Imagem Resultante')
5 mmplot([[it]],['set yrange [0:256]','set xrange [0:256]'], ptitle='Funcao aplicada')
6 h = iahistogram(g)
7 mmplot([[h]],['set yrange [0:'+str(h.max())+']','set xrange [0:256]'], ptitle='Histograma')
Warning: downcasting image from int32 to uint16 (may lose precision)

Imagem Resultante

A interpretação dessa transformação é interessante.

Observe o histograma da imagem original (no começo do exercício). há um pico por volta do valor 200 em tom de cinza. Essa parte representa o céu da imagem.

Na transformação que apliquei acima todos os pixels com valor entre 175 e 225 receberam o valor 100.

Observe na imagem que o céu ficou mais escuro e houve uma alteração no histograma aparecendo um pico no valor 100.

2 - Implementação de função semelhante a iaapplylut

A iaapplylut pode ser implementada utilizando o comando take(I,V), conforme abaixo:

1 def iaapplylut_ex5(f,it):
2   g = take(it,f)
3   return g

O comando take() recebe como parametro um vetor I de índices e um vetor V com valores. É retornado um vetor com o mesmo tamanho do vetor I contendo os respectivos valores de V.

Veja abaixo a utilização dessa função com a transformação Negativo

1 it = 255 - arange(256)
2 g = iaapplylut_ex5(f,it)
3 iashow(g,title='Funcao aplicada: Negativo')
4 
5 h = iahistogram(g)
6 mmplot([[h]],['set yrange [0:'+str(h.max())+']','set xrange [0:256]'], ptitle='Histograma')
Warning: downcasting image from int32 to uint16 (may lose precision)

Funcao aplicada: Negativo

Observe que o histograma é semelhante ao histograma gerado pela função iaapplylut na parte 1.2 desse exercício.

3 - Função interativa de melhoria de contraste da imagem

  • 3.1 - Calculando parâmetros de entrada

O enunciado do exercício diz que os parâmetros de entrada são: Wi,Li largura e intensidade média de entrada, e Wo, Lo, largura e intensidade média de saída.

A função abaixo calcula os dois pontos de inflexão das retas em função de 4 parâmetros: Wi,Li,Wo, Lo.

1 # Dados os parâmetros de entrada do exercício, retorna os dois pontos de inflexão das retas
2 def get_pontos_inflexao(Li,Wi,Lo,Wo):
3   x1 = Li - Wi / 2
4   x2 = x1 + Wi
5   y1 = Lo - Wo / 2
6   y2 = y1 + Wo
7   return [ [x1,y1] , [x2,y2] ]
  • 3.2 - Obtendo a equação da reta

Referência: http://www.dft.if.uerj.br/cursos/FisicaI/apostilas/LAB3/node6.html

1 # dados os pontos P1 e P2, retorna coeficiente a e b da reta
2 def get_ab(P1,P2):
3   x1,y1 = P1
4   x2,y2 = P2
5   a = (y2-y1)/(x2-x1)
6   b = y1 - a * x1
7   return [a,b]
 1 # RETA 1
 2 P1=[0.0,0.0]
 3 P2=[2.0,3.0]
 4 a,b = get_ab(P1,P2)
 5 reta1 = a * arange(10) + b
 6 mmplot([[reta1]],['set yrange [0:10]','set xrange [0:10]'], ptitle='Reta 1')
 7 print 'reta 1'
 8 print 'a = '+str(a)+', b = '+str(b)
 9 print 'pontos: '+str(reta1)
10 
11 # RETA 2
12 P1=[2.0,3.0]
13 P2=[6.0,4.0]
14 a,b = get_ab(P1,P2)
15 reta2 = a * arange(10) + b
16 mmplot([[reta2]],['set yrange [0:10]','set xrange [0:10]'], ptitle='Reta 2')
17 print 'reta 2'
18 print 'a = '+str(a)+', b = '+str(b)
19 print 'pontos: '+str(reta2)
20 
21 # RETA 3
22 P1=[6.0,4.0]
23 P2=[10.0,10.0]
24 a,b = get_ab(P1,P2)
25 reta3 = a * arange(10) + b
26 mmplot([[reta3]],['set yrange [0:10]','set xrange [0:10]'], ptitle='Reta 3')
27 print 'reta 3'
28 print 'a = '+str(a)+', b = '+str(b)
29 print 'pontos: '+str(reta3)
reta 1
a = 1.5, b = 0.0
pontos: [  0.    1.5   3.    4.5   6.    7.5   9.   10.5  12.   13.5]
reta 2
a = 0.25, b = 2.5
pontos: [ 2.5   2.75  3.    3.25  3.5   3.75  4.    4.25  4.5   4.75]
reta 3
a = 1.5, b = -5.0
pontos: [-5.  -3.5 -2.  -0.5  1.   2.5  4.   5.5  7.   8.5]

  • 3.3 - Montando a reta de mapeamento de contraste ou de intensidade

Essa reta é obtida através da junção das três retas acima.

 1 P0 = [0.0,0.0]
 2 P1 = [2.0,3.0]
 3 P2 = [6.0,4.0]
 4 P3 = [10.0,10.0]
 5 
 6 a1,b1 = get_ab(P0,P1)
 7 a2,b2= get_ab(P1,P2)
 8 a3,b3 = get_ab(P2,P3)
 9 
10 criterio1 = (arange(10) <= P1[0])
11 criterio2 = (arange(10) > P1[0]) & (arange(10) <= P2[0])
12 criterio3 = (arange(10) > P2[0])
13 
14 it = where( criterio1 , a1 * arange(10) + b1 ,
15          where( criterio2 , a2 * arange(10) + b2 ,
16              where( criterio3 , a3 * arange(10) + b3 , 0)
17          )
18      )
19 
20 mmplot([[it]],['set yrange [0:10]','set xrange [0:10]'], ptitle='reta de mapeamento de contraste ou de intensidade')

Criando função que monta a reta de mapeamento de contraste ou de intensidade conforme realizado acima

 1 def get_reta_mapeamento(P1,P2):
 2   a1,b1 = get_ab( [0.0,0.0] , P1 )
 3   a2,b2= get_ab( P1 , P2 )
 4   a3,b3 = get_ab( P2 , [256.0,256.0] )
 5 
 6   criterio1 = (arange(256) <= P1[0])
 7   criterio2 = (arange(256) > P1[0]) & (arange(256) <= P2[0])
 8   criterio3 = (arange(256) > P2[0])
 9 
10   it = where( criterio1 , a1 * arange(256) + b1 ,
11            where( criterio2 , a2 * arange(256) + b2 ,
12                where( criterio3 , a3 * arange(256) + b3 , 0)
13            )
14        )
15 
16   return it
1 P1 = [100.0,50.0]
2 P2 = [150.0,200.0]
3 
4 it = get_reta_mapeamento(P1,P2)
5 
6 mmplot([[it]],['set yrange [0:256]','set xrange [0:256]'], ptitle='reta de mapeamento de contraste ou de intensidade')

  • 3.4 - Utilizando a função get_reta_mapeamento para alterar o contraste da imagem.

O objetivo deste teste é aumentar o contraste da região onde aparece o homem com a câmera.

1 imgname = 'cameraman.pgm'
2 f = iaread(imgname)
3 iashow(f,title=imgname)
4 h = iahistogram(f)
5 mmplot([[h]],['set yrange [0:'+str(h.max())+']','set xrange [0:256]'], ptitle='Histograma da imagem original')

cameraman.pgm

1 Li = 42.5
2 Wi = 65.0
3 Lo = 105.0
4 Wo = 190.0
5 P1,P2 = get_pontos_inflexao(Li,Wi,Lo,Wo)
6 print 'Pontos de inflexão: '+str(P1)+', '+str(P2)
7 
8 it = get_reta_mapeamento(P1,P2)
9 mmplot([[it]],['set yrange [0:256]','set xrange [0:256]'], ptitle='Funcao aplicada')
Pontos de inflexão: [10.0, 10.0], [75.0, 200.0]

1 g = iaapplylut(f, it)
2 iashow(g,title='Imagem resultante')
3 h = iahistogram(g)
4 mmplot([[h]],['set yrange [0:'+str(h.max())+']','set xrange [0:256]'], ptitle='Histograma da imagem resultante')
Warning: downcasting image from double to uint16 (may lose precision)

Imagem resultante

  • Análise do resultado:

O objetivo da minha transformação foi aumentar o contraste da região onde aparece o homem com a câmera.

Analisando o histograma da imagem original observei que há um pico nos pixels mais escuros. Esse pico é formado pelos pixels da região do homem. A transformação que aplique pega os pixels entre 10 e 75 e mapeia os mesmos para o intervalo entre 10 e 200. Isso faz com que os valores dos pixels fiquem mais separados.

Observe na imagem resultante que os detalhes da roupa do homem ficaram mais nítidos. Isso demonstra que a transformação de contraste obteve sucesso ao destacar a região que escolhi.

Observe também no histograma da imagem resultante que o pico dos pixels escuros diminuiu ao mesmo passo que o pico dos pixels mais claros aumentou. Isso demonstra que o mapeamento funcionou conforme esperado.