segunda-feira, 16 de novembro de 2015

Cuidar da imagem...

Durante as aulas vimos como se podia representar uma imagem a preto e branco através de uma lista de listas de 0s e 1s. A questão concreta colocada na aula era a de produzir o negativo de uma imagem, sem destruir a imagem original. O exercício não era difícil. Temos que percorrer toda a imagem e efectuar a alteração dos 0s para 1s e os 1s para 0s. Como a estrutura é 2D vamos precisar de dois ciclos. Como não queremos a destruição da imagem original precisamos construir uma nova. Uma solução que respeite o enunciado é a seguinte:
01.def negativo(imagem):
02.    nova_imagem = []
03.    for linha in imagem:
04.        nova_linha = []
05.        for coluna in linha:
06.            if coluna == 0:
07.                nova_linha.append(1)
08.            else:
09.                nova_linha.append(0)
10.        nova_imagem.append(nova_linha)
11.    return nova_imagem
Como se pode ver a imagem é construída a partir de uma imagem vazia. Os dois ciclos são percorridos pelo conteúdo.

Podemos fazer de modo um pouco diferente. Criamos uma cópia da imagem inicial, e alteramos de acordo com o enunciado. Neste caso percorremos os ciclos for pela posição, pois estas são necessárias para a actualização da imagem. A cópia é feita usando o método deepcopy do módulo copy para assegurar que as duas imagens ficam totalmente separadas.
01.import copy
02. 
03.def negativo(imagem):
04.    copia = copy.deepcopy(imagem)
05.    for linha in range(len(imagem)):
06.        for coluna in range(len(imagem[0])):
07.            if copia[linha][coluna] == 0:
08.                copia[linha][coluna] = 1
09.            else:
10.                copia[linha][coluna] = 0
11.    return copia
Estas duas versões parecem esgotar as alternativas. Mas não é bem verdade isso. Podemos evitar o recurso ao teste no interior dos dois ciclos.
1.def negativo_b(imagem):
2.    copia = copy.deepcopy(imagem)
3.    for linha in range(len(imagem)):
4.        for coluna in range(len(imagem[0])):
5.            copia[linha][coluna] = (copia[linha][coluna] + 1) %  2
6.    return copia
O que fizemos? Usemos o conhecimento de que o resto da divisão de um numero por dois ou é 0 ou é 1. No nosso caso somamos 1 ao conteúdo da matriz. Se for 0, fica 1. Se for 1 passa a 0! E pronto. Agora é que esgotámos as alternativas. Certo? Não, errado! Mais uma variante:
1.def negativo_c(imagem):
2.    copia = copy.deepcopy(imagem)
3.    for linha in range(len(imagem)):
4.        for coluna in range(len(imagem[0])):
5.            copia[linha][coluna] ^= 1
6.    return copia
Esta solução é semelhante à anterior, são que usamos a operação binária ou exclusivo.

Sem comentários:

Enviar um comentário