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:
def negativo(imagem):
    nova_imagem = []
    for linha in imagem:
        nova_linha = []
        for coluna in linha:
            if coluna == 0:
                nova_linha.append(1)
            else:
                nova_linha.append(0)
        nova_imagem.append(nova_linha)
    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.
import copy

def negativo(imagem):
    copia = copy.deepcopy(imagem)
    for linha in range(len(imagem)):
        for coluna in range(len(imagem[0])):
            if copia[linha][coluna] == 0:
                copia[linha][coluna] = 1
            else:
                copia[linha][coluna] = 0
    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.
def negativo_b(imagem):
    copia = copy.deepcopy(imagem) 
    for linha in range(len(imagem)):
        for coluna in range(len(imagem[0])):
            copia[linha][coluna] = (copia[linha][coluna] + 1) %  2
    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:
def negativo_c(imagem):
    copia = copy.deepcopy(imagem) 
    for linha in range(len(imagem)):
        for coluna in range(len(imagem[0])):
            copia[linha][coluna] ^= 1
    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