Construção de Algoritmos
IFMS NA

Projeto - Filtros de Imagem

Junho 2023

Lembre-se: o projeto deve ser entregue no Moodle da sua classe!
Vai ser feita uma apresentação do projeto. O instrutor se reserva o direito de fazer questionamentos sobre todas as etapas do desenvolvimento do projeto para qualquer participante do trabalho.
A sua nota no projeto será parte pela implementação das funcionalidades, parte pela entrevista.

Um pouco sobre cores ...


O comprimento de onda que nossos olhos podem detectar (o espectro de luz visível) é apenas uma fração do espectro de energia eletromagnético. As ondas mais curtas visíveis são as ondas no espectro do azul. Ondas com comprimento de onda mais curtos, como o ultra-violeta ainda são detectáveis, apenas não são visíveis ao olho humano. Na outra ponta do espectro visível temos as ondas vermelhas. Onda infravermelhas, como as usadas em controle-remoto são comunmente usadas, mas não vísiveis.

Espectro de luz visível
Espectro de luz (cor) visível.

Se o espectro de luz vísivel for dividido, as cores predominantes são o vermelho, o verde e o azul (Red, Green, Blue - RGB). Essas cores são também chamadas de cores primárias. O modelo RGB é chamado de modelo de cor aditivo pois todas as outras cores são combinações das cores primárias. Por exemplo, o ciano é a mistura do azul puro com o verde puro.

Modelo aditivo RGB
O Modelo Aditivo de Cor RGB.

Representando cores em computadores ...


Televisores e monitores de computador (atualmente praticamente indistinguiveis uns dos outros atualmente) criam cores usando as cores primárias da luz. Cada pixel (a menor unidade de reprodução de luz de um dispotivo) em um monitor começa como preto (ausência de luz). Quando as unidades de luz vermelha, verde e azul de um pixel são iluminadas simultaneamente, esse píxel se torna branco. Controlando a quantidade de cada um das unidades de luz, chamadas de canais de cor, nós podemos representar as cores do espectro visível em um monitor.

Atualmente, o valor da cor de cada pixel é armazenado usando os valores de cada canal do modelo RGB. Cada canal é representado por um byte (8 bits). Como um byte pode representar no máximo 256 valores, cada canal varia de 0 (ausência total da cor) a 255 (presença total da cor). Como temos 3 canais de cores, são necessários 3 bytes (24 bits) para cada pixel de uma imagem! Pode não parecer muito atualmente, mas antigamente processar essa quantidade de dados era um grande gargalo...

Além dos três canais de cor (RGB), o modelo RGB Alpha utilizado pelos computadores atuais adicionaram um novo canal para transparência (alpha). Caso o valor do canal seja 0 o pixel será completamente transparente, caso o canal tenha o valor seja 255 o canal será completamente opaco.

Canais RGB
Canais RGB alpha.

Usando essa representação em três canais mais o canal de transparência (alfa), 256 valores por canal, podemos representar:

Manipulando imagens (e cores) em Python


Geralmente, imagens são descritas em forma de matrizes. Por exemplo, uma imagem 29x20 tem 29 linhas e cada linha tem 20 pixels, num total de 580 pixels! Em geral é isso que chamamos de resolução da imagem. Um monitor Full HD suporta uma resolução de 1920 x 1080 pixels. Um monitor 4K suporta uma resolução de até 3840 x 2129 pixels.

Toad em Pixel Art
Representação de uma imagem usando apenas 29x20 pixels.

Uma imagem em Python é representada por uma matriz onde cada elemento da matriz (linha, coluna) corresponde a um pixel. Se a imagem estiver no modo RGBA, cada pixel contém 4 valores. Se estiver no modo RGB contém 3 valores.

Canais RGB em JavaScript
Canais RGB alpha em Python (RGBA).

Filtros de Imagem


Filtros de imagem são manipulações dos pixels de uma imagem de modo a transforma-la mas sem descaracterizá-la por completo. Existem filtros complexos, tais como os filtros no Stories do Instagram, que requerem não apenas a manipulação pixel a pixel da imagem mas também a manipulação de várias características de uma imagem como um todo. Neste projeto específico vamos trabalhar apenas com filtros que manipulam os pixels de uma imagem, pois são mais simples de entender e implementar:

Nas próximas seções vamos apresentar a teoria de cada um dos filtros. Para o filtro negativo será fornecido o código exemplo para que vocês possam continuar o desenvolvimento dos demais filtros.

A REPL modelo do projeto está disponível aqui.

Vocês podem implementar todos os filtros no mesmo arquivo Python. O projeto já vem com duas imagens padrão de teste, mas vocês podem utilizar outras imagens se assim desejarem.


Os códigos usados para acessar os pixels de cada imagem já estão corretamente inseridos no arquivo main.py. Explicarei brevemente o que cada parte do código objetiva:

from PIL import Image
image = Image.open('gato2.jpg')
O módulo PIL (Pillow) se encarrega de carregar e apresentar os pixels da imagem. Carregamos em seguir a imagem "gato2.jpg" dentro da variavel imagem.
w = image.size[0]
h = image.size[1]
A propriedade size da imagem é uma lista onde o primeiro elemento é a largura (width -- linhas) e o segundo a altura (height -- colunas)
for y in range(0, h):
  for x in range(0, w):
Aqui temos dois loops. O mais interno "varre" as linhas, e o mais externo "varre" as colunas. Desta forma, x e y são a localização de cada pixel da imagem.
    R, G, B = im.getpixel((x, y))
A função getpixel retorna os valores, separados, de cada um dos canais de cor, na ordem: vermelho, verde, azul.
    nR = 255- R
    nG = 255- G
    nB = 255- B
Aqui implementamos o filtro propriamente dito. No caso do filtro negativo, cada pixel é invertido ao subtrair 255 do valor do seu canal.
    image.putpixel((x,y) , (nR, nG, nB))
Os novos valores de cada canal são armazenados no seu respectivo pixel usando a função putpixel
image.show()
Pedimos para o Python abrir uma nova janela com a imagem processada.