domingo, 18 de outubro de 2009

Problema 3.11

Esta questão envolve imagens a preto e branco representadas por listas de listas. Os valores podem ser 0 (branco) e 1 (preto). Na lista inicial cada um dos seus elementos (uma lista!) representa uma linha. Em cada linha os elementos representam os pixeis (preto ou branco). Criar um negativo obriga a transformar os pixeis brancos em pretos e vice-versa. Como são todos temos que percorrer, por certa ordem, todas as posições (pixeis) da imagem. Na realidade, uma lista de listas pode representar qualquer matriz e a nossa questão mais complexa é: como percorrer uma matriz? A resposta não é difícil: usar dois ciclos imbricados. É isso que o programa documenta.

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 imagem[linha][coluna] == 0:
08.   copia[linha][coluna] = 1
09.  else:
10.   copia[linha][coluna] = 0
11.return copia


Notar que por razões de segurança (não queremos a imagem original estragada) trabalhamos sobre uma cópia. Para termos garantia absoluta de que a imagem original não é afectada usamos o módulo copy e, dentro deste, a função deepcopy. Não chega fazer apenas copia = lista[:]. Isto porque essa cópia seria apenas ao primeiro nível da lista original (shallow copy). Assim, se tivermos elementos mutáveis a esse nível podemos ter problemas. Como isso acontece no nosso caso (os elementos do primeiro nível são listas) e vamos alterá-los, então teríamos garantidamente problemas caso não se usasse uma cópia profunda (deepcopy) que copia a todos os níveis. Atente~se ainda como se faz a indexação. Neste caso, como é uma lista de listas (uma matriz), precisamos de dois índices. O primeiro, dá-nos a linha, o segundo, a coluna (dentro da linha escolhida). A notação copia[linha,coluna] daria erro.


Mas será esta a única maneira de proceder? Não. Podíamos por exemplo, não usar um if dentro dos dois ciclos.


1.import copy
2. 
3.def negativo_b(imagem):
4.copia = imagem[:] # just in case...
5.for linha in range(len(imagem)):
6. for coluna in range(len(imagem[0])):
7.  copia[linha][coluna] = (imagem[linha][coluna] +1) %  2
8.return copia


Notar o código da linha 7.

Sem comentários:

Enviar um comentário