Exercício3 de IA636-2009

Autor:Matias
Data:26/03/2009

Questão 1

Utilizando a função gedada no primeiro exercício mas com pequenas modifações para suportar especifações de cores, foi gerada a imagem xadrez de dimensões 100x100 e tamanho de casa 2:

def cria_xadrez_tile(imagemw, imagemh, casa, cor1, cor2):

    A = zeros([casa,casa])+cor1
    B = zeros([casa,casa])+cor2
    C = concatenate((A,B),axis=1)
    D = concatenate((B,A),axis=1)
    TILE = concatenate((C,D),axis=0)
    restow = imagemw % (2*casa)
    restoh = imagemh % (2*casa)

    if (restoh==0) and (restow==0):
        MATRIZ = tile(TILE, [(imagemh//(2*casa)),(imagemw // (2*casa))])
    else:
        MATRIZ_TEMP = tile(TILE, [(imagemh//(2*casa))+1,(imagemw // (2*casa))+1])
        MATRIZ=zeros([imagemh,imagemw])
        MATRIZ=MATRIZ_TEMP[0:imagemh,0:imagemw]

    return MATRIZ


adshow(cria_xadrez_tile(200,200,2,0,255),title = "Ladrilho=2, Cor1=0, Cor2=255")

Ladrilho=2, Cor1=0, Cor2=255

Análise do realce automatico

Como visto em aula a função mmshow normaliza as imagens antes de exibi-las. Para exemplificar isso, mostramos duas imagens geradas com tons de cinza 0 e 50, uma com pixels de referência adicionados e outra sem:

imagem = cria_xadrez_tile(200,200,2,0,50)
mmshow(uint16(imagem),title = "mmshow: Sem pontos de referência")
imagem[0,0]=0
imagem[0,1]=255
mmshow(uint16(imagem),title = "mmshow: Com pontos de referência")

mmshow: Sem pontos de referência

mmshow: Com pontos de referência

A função adshow entretanto, faz esse realce.

imagem = cria_xadrez_tile(200,200,2,0,50)
adshow(imagem,title = "adshow: Sem pontos de referência")
imagem[0,0]=0
imagem[0,1]=255
adshow(imagem,title = "adshow: Com pontos de referência")

adshow: Sem pontos de referência

adshow: Com pontos de referência

Entretanto, foi observado que a função adshow() tem um comportamento "ciclico" em relação a valores maiores que 255, que é considerado o máximo. 256 é novamente o tom mais escuro, e assim por diante. Foram sempre colocados os pontos de referência com valores 0 e 255:

imagem = cria_xadrez_tile(200,200,2,0,255)
imagem[0,0]=0
imagem[0,1]=255
adshow(imagem,title = "adshow: Cor1: 0, Cor2: 255")

imagem = cria_xadrez_tile(200,200,2,0,256)
imagem[0,0]=0
imagem[0,1]=255
adshow(imagem,title = "adshow: Cor1: 0, Cor2: 256")

imagem = cria_xadrez_tile(200,200,2,0,511)
imagem[0,0]=0
imagem[0,1]=255
adshow(imagem,title = "adshow: Cor1: 0, Cor2: 511")

imagem = cria_xadrez_tile(200,200,2,0,512)
imagem[0,0]=0
imagem[0,1]=255
adshow(imagem,title = "adshow: Cor1: 0, Cor2: 512")

adshow: Cor1: 0, Cor2: 255

adshow: Cor1: 0, Cor2: 256

adshow: Cor1: 0, Cor2: 511

adshow: Cor1: 0, Cor2: 512

Com isso, chega-se a conclusão que se pode usar o adshow() sem os pontos de referência, mas que os valores devem ficar restritos a 8 bits (0-255).

Contraste entre mosaicos

Conforme pedido foi gerada a imagem com as mesmas dimensões anteriroes, mas com intensidades 110 e 111:

adshow(cria_xadrez_tile(200,200,2,110,111),title = "Mosaico: 2, Cor1: 110, Cor2: 111")

Mosaico: 2, Cor1: 110, Cor2: 111

É importante notar que a percepção entre tons de cinza é afetada pela cor de fundo e cor do ambiente em geral Uma tentativa de ilustrar esse efeito é colocar molduras de intensidades diferentes na imagem como a seguir, onde as intensidades dos mozaicos são 110 e 113:

imagem = cria_xadrez_tile(200,200,2,110,113)

imagem2 = iapad(imagem,[100,100],0)
adshow(imagem2)

imagem2 = iapad(imagem,[100,100],255)
adshow(imagem2)

Entretanto, é a pessoa ainda estará sujeita aos efeitos do resto do ambiente, como iluminação local, configuração do monitor, o que mais está no campo de visão (cor da página), etc. Um exemplo típico de como o ambiente influência nossa capacidade de distinguir tons é nossa capacidade de se adatpar e enxergar em ambientes de baixa luminosidade.

Feita essa ressalva, como os exemplo aqui estarão sendo observados no mesmo ambiente, a comparação relativa entre eles ainda é válida.

Segue uma comparação de diferença de intensidade. Tem se como base 3 intensidades:
  • 5 + diferença
  • 110 + diferença
  • 245 + diferença
1 for diff in range (0,6):
2     adshow(cria_xadrez_tile(200,200,2,5,5+diff),title="Diferença: " + str(diff))
3 
4 for diff in range (0,6):
5     adshow(cria_xadrez_tile(200,200,2,110,110+diff),title="Diferença: " + str(diff))
6 
7 for diff in range (0,6):
8     adshow(cria_xadrez_tile(200,200,2,245,245+diff),title="Diferença: " + str(diff))

Diferença: 0

Diferença: 1

Diferença: 2

Diferença: 3

Diferença: 4

Diferença: 5

Diferença: 0

Diferença: 1

Diferença: 2

Diferença: 3

Diferença: 4

Diferença: 5

Diferença: 0

Diferença: 1

Diferença: 2

Diferença: 3

Diferença: 4

Diferença: 5

Em uma avaliação subjetiva pessoal, com a intensidade base 110, uma diferença de 3 já é perceptivel.. Nas bases mais nos extremos parece que a diferença precisa ser um pouco maior.

Selecionado então a diferença menor mas ainda perceptível (intensidades 110 e 113), fazemos então uma comparação com o tamanho do mozaico:

1 for mozaico in [2,10,20,50]:
2     adshow(cria_xadrez_tile(200,200,mozaico,110,113),title="Mozaico:"+ str(mozaico)+" Dif:3")
3 adshow(cria_xadrez_tile(400,200,200,110,113),title="Mozaico:200 Dif:3")

Mozaico:2 Dif:3

Mozaico:10 Dif:3

Mozaico:20 Dif:3

Mozaico:50 Dif:3

Mozaico:200 Dif:3

O aumento dos mozaicos aparenta facilitar a percepção da diferença das intensidades. Como um teste final, vamos manter o tamanho do mozaico em 20 e alterar a diferença de intensidade:

1 for diff in range (0,4):
2     adshow(cria_xadrez_tile(200,200,50,110,110+diff),title="Mozaico:50 Dif: " + str(diff))

Mozaico:50 Dif: 0

Mozaico:50 Dif: 1

Mozaico:50 Dif: 2

Mozaico:50 Dif: 3

Mais uma vez em um teste subjetivo, agora parece que com uma diferença de 2 já é possivel diferenciar as duas intensidades, embora os mozaicos ainda não aparentem muita definicação. Entretando, com a mesma diferença de 3, os mozaicos ficaram muito mais vísiveis e perceptíveis.

Questão 2

Para essa questão foram implementadas 3 rotinas.

  • reduzir_espacial: Reduz a resolução espacial da imagem.
  • reduzir_espacial_com_media: Reduz a resolução espacial da imagem, fazendo uma média de todos os pontos da area "reduzida".
  • reduzir_cor: Reduz o número de tons de cinza.

Ambas as funções de redução espacial foram feitas para retornar uma imagem com as mesmas dimensões da original, facilitando as comparações visuais. A reduzir_espacial() considera apenas a cor do primeiro pixel do quadrado que será reduzido para um pixel, já reduzir_espacial_com_media() faz a média de todos os pixels nessa área. Infelizmente o método desenvolvido acabou sendo iterativo, mas ainda assim é interessante para comparar os resultados.

 1 def reduzir_espacial(imagem, reducao):
 2     tamanho_x,tamanho_y = imagem.shape
 3     X,Y = meshgrid(range(0,tamanho_x-1),range(0,tamanho_y-1))
 4     X = ((X / reducao) * reducao)
 5     Y = ((Y / reducao) * reducao)
 6     return imagem[Y,X]
 7 
 8 def reduzir_espacial_com_media(imagem, reducao):
 9     tamanho_x,tamanho_y = imagem.shape
10 
11     linhas = array_split(imagem,tamanho_x/reducao,axis=0)
12 
13     imagem_reduzida = zeros([tamanho_x/reducao,tamanho_y/reducao])
14     indice_linha=0
15 
16     for linha in linhas:
17         colunas = array_split(linha,tamanho_y/reducao,axis=1)
18         indice_coluna = 0;
19         for coluna in colunas:
20             imagem_reduzida[indice_linha,indice_coluna]=mean(coluna)
21             indice_coluna = indice_coluna+1
22         indice_linha = indice_linha + 1;
23 
24     imagem_reduzida = repeat(imagem_reduzida,reducao,axis=0)
25     imagem_reduzida = repeat(imagem_reduzida,reducao,axis=1)
26     return imagem_reduzida
27 
28 
29 def reduzir_cor(imagem, reducao):
30     minimo_antigo = imagem.min()
31     maximo_antigo = imagem.max()
32     imagem = ((imagem // reducao))
33     imagem = ianormalize(imagem,[minimo_antigo,maximo_antigo])
34     return imagem

Imagem original

A seguinte imagem é a original usada para as operações:

imagem_carregada = mmreadgray('boat.ppm')
adshow(imagem_carregada,title="Imagem original")

Imagem original

Redução espacial

Foram realizadas reduções espaciais com os fatores de 2x, 4x e 8x.

for reducao in [2,4,8]:
    adshow(reduzir_espacial(imagem_carregada,reducao),title="Redução espacial: " + str(reducao))
    adshow(reduzir_espacial_com_media(imagem_carregada,reducao),title="Redução espacial com média: " + str(reducao))

Redução espacial: 2

Redução espacial com média: 2

Redução espacial: 4

Redução espacial com média: 4

Redução espacial: 8

Redução espacial com média: 8

Com fator 2, ainda é possível identificar a imagem original sem dificuldades, embora os detalhes como texto já fiquem inteligíveis, especialmente na função sem média. De maneira geral, objetos com curvas e retas não verticais ou horizontais em fundo com contraste são que os que mais se pronunciam com a perda da resolução (fênonemo de aliasing). A função com média suaviza esse problema (já que na prática acaba se comportando como uma técnica de anti-aliasing) mas mesmo com 2x a diferença na imagem já é grande.

Com fator 4 já fica mais díficil reconhecer a imagem original, mas mais uma vez a função com média ajuda.

Já com fator 8, ambas as funções não conseguem produzir uma imagem reconhecível. A imagem com média ainda é mais agradavel de observar por não ter tanto contraste brusco entre os pontos, mas ainda assim a perda de informação é muito grande.

Redução em tons de cinza

for reducao in [2,4,8,16,32,64,128]:
    adshow(reduzir_cor(imagem_carregada,reducao),title="Redução em cor: " + str(reducao))

Redução em cor: 2

Redução em cor: 4

Redução em cor: 8

Redução em cor: 16

Redução em cor: 32

Redução em cor: 64

Redução em cor: 128

Como a imagem escolhida não apresenta altos contrastes, na medida que se reduz o número de tons de cinza, vários detalhes vão se perdendo rapidamente. Até um fator 16x o efeito é visível mas tolerável. Com 32x a perda de informações visuais já começa ficar grave, por exemplo o carro no fundo da imagem, que em 64x é praticamente perdido. Em 128x fica quase impossível reconhecer a imagem original.

Para comparar, pegamos uma imagem com alto contraste:

imagem_carregada = mmreadgray('cameraman.pgm')
adshow(imagem_carregada,title="Imagem original")

for reducao in [2,4,8,16,32,64,128]:
    adshow(reduzir_cor(imagem_carregada,reducao),title="Redução em cor: " + str(reducao))

Imagem original

Redução em cor: 2

Redução em cor: 4

Redução em cor: 8

Redução em cor: 16

Redução em cor: 32

Redução em cor: 64

Redução em cor: 128

Embora também ocorram perda de informações e detalhes, a imagem geral ainda é reconhecível, mesmo com um fator 128x (2 cores).

Comentários finais

Embora a perda de informações seja sempre a mesma, esse exercício demonostrou que dependendo das técnicas, e mesmo do tipo da imagem, ainda se pode extrair bastante detalhes e caracteristicas das imagens reduzidas, em especial para reduções não tão altas. No caso da redução espacial o uso da média preserva detalhes e a suavidade da imagem, enquanto no caso da redução dos tons de cinza uma imagem com alto contraste ainda é reconhecível mesmo com um número muito reduzido de cores.