Nov
10

Processamento de imagens como mágica

Autor // Rafael Casale Abe

Certos conceitos de processamento de imagens são relativamente simples, porém resultados em forma de imagem podem impressionar e até dar a falsa impressão de que é extremamente complicado. Utilizar uma linguagem como Python [1] e a biblioteca PIL [2] nessa tarefa, a deixará ainda mais simples.

Escala de Cinza

Uma imagem será manipulada de diversas formas mas com um único resultado: transformar uma imagem colorida (RGB) em escala de cinza. O RGB é um padrão de sistema de cores para imagem e video e é um acrônimo para Red Blue Green, ou em português Vermelho, Azul e Verde, ou seja, é a forma como as cores são combinadas para se obter outras cores [3].

Um pixel é a quantidade de dados que representa a menor unidade de cor de uma imagem [digital]. No caso do padrão RGB um pixel contém no mínimo três bytes, cada qual deve conter informação que determina a 'quantidade' de Vermelho (R), Verde (G) e Azul (B) respectivamente. Uma imagem está em escala de cinza quando todos os os bytes de cada pixel tem o mesmo valor. Por exemplo:
R G B
Color 200 178 30
Escala de cinza 136 136 136

Conceitualmente, para que a imagem colorida seja transformada em escala de cinza, é necessário percorrer tal imagem pixel-a-pixel e modificando-a de forma que os valores de RGB de cada um desses pixel seja o mesmo. Mas que valor seria esse? Magicamente, para que a imagem só perca informação de cor, a maneira mais simples de fazer isso é obtendo os valores RGB do pixel atual, calcular a média aritimética e reaplicar o novo valor para R, G e B do respectivo pixel, ou seja:
valor_pixel = (pixel[R], pixel[G], pixel[B])/3;
pixel[R] = valor_pixel;
pixel[G] = valor_pixel;
pixel[B] = valor_pixel;
 

Mão na massa

O python é uma linguagem interpretada, intuitiva e muito divertida, além de sua virtual machine ser Software Livre. Juntamente com o PIL (Process Imaging Library) torna o processamento de imagens muito mais simples e muito poderoso.

Não será tratado aqui da instalação do interpretador da linguagem e bilbioteca, muito menos de IDEs, já que um simples editor de textos (e.g. vim [4]) já é mais que suficiente para a ocasião.

A cobaia

A imagem a ser alterada será a imagem supercolorida abaixo:
A cobaia
Para conhecê-la mais de perto, deve-se perguntar a ela mesma sobre informações importantes como formato, tamanho, modo e etc. Para isso, basta invocar o IDLE do python através do interpretador de comandos:
$ python
Python 2.5.2 (r252:60911, Mar  1 2008, 13:52:45) 
[GCC 4.2.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
 

Carregar a biblioteca PIL:
>>> import Image
 

E carregar a imagem fazendo as perguntas certas às pessoas corretas:
>>> img_orig = Image.open("sandpoint.png")
>>> img_orig.format
'PNG'
>>> img_orig.size
(690, 458)
 
Foi descoberto agora que a imagem utiliza o formato PNG (Portable Network Graphics) e que tem dimensões de 640 por 458 pixels. O próximo passo deve ser a iteração entre os pixels da imagem, obtendo seus respctivos valores e alterando-os de acordo com a teoria anteriormente explicada. Cada novo pixel com seu respectivo novo valor, será colocado em uma nova imagem para que a imagem original seja preservada e então comparada com seu resultado.
# isso é um comentário em python :)
# criando uma nova imagem com as mesmas dimensões da original
>>> img_nova = Image.new("RGB", img_orig.size)
 
O primeiro argumento do método new() é o modo qual o pixel irá se comportar dentro da imagem e o argumento size é uma tupla contendo o tamanho em X e Y. Depois disso, basta iterar entre os eixos X e Y da imagem, processando o pixel e colocando-o na imagem destino:
>>> for for x in range(img_orig.size[0]):
...  for y in range(img_orig.size[1]):
  # calcula o novo valor do pixel
...    valor = (img_orig.getpixel((x,y))
[0]+img_orig.getpixel((x,y)) [1]+img_orig.getpixel((x,y))[2])/3 
  # determina o novo pixel com o mesmo valor para R,G e B
...  img_nova.putpixel((x,y), (valor,valor,valor))
# salva em um novo arquivo
img_nova.save("sandpoint_pb.png")
 

Utilizando o interpretador de comandos, é possível verificar o novo arquivo criado:
$ ls *.png
sandpoint.png  sandpoint_pb.png
 
E utilizando um visualizador de imagem, tem-se:
P&B

As diversas facetas de uma imagem

Para tentar provar e/ou elucidar alguns conceitos aqui expostos, interessante torna-se variar um pouco a lógica aplicada. Como é possível manipular os valores dos pixels e que a combinação dos três bytes determina a cor de cada um deles, é possível extraír, por exemplo, cada uma das camadas de cor da imagem apenas modificando a linha:

img_nova.putpixel((x,y), (valor,0,0)), para tons de vermelho:

serialkiller

img_nova.putpixel((x,y), (0,valor,0)), para tons de verde:

hulk

ou img_nova.putpixel((x,y), (0,0,valor)), para tons de azul:

urublue

Viu? Parece mágica, mas é python :)

Referências:
[1] http://www.python.org
[2] http://www.pythonware.com/products/pil/
[3] http://pt.wikipedia.org/wiki/RGB
[4] http://www.vim.org/


* Esse artigo está licenciado sob GNU FDL.
Artigos Relacionados:

blog comments powered by Disqus