Prazo de entrega recomendado:
Iremos construir um editor interativo de imagens capaz de realizar diversas operações, como destaque e aplicação de filtros. Para isso, será necessário manipular matrizes.
A visão é um dos sentidos mais complexos do ser humano. Ela permite capturar as mais diferentes imagens ao nosso redor. Nós percebemos essas imagens através da luz, que traz uma quantidade abundante de dados. Com o tempo, aprendemos a processar esses dados, identificar e classificar objetos de maneira tão simples, que encaramos a visão de maneira natural e a entendemos como um processo elementar.
Replicar esse processo com os computadores, no entanto, é desafiador. A primeira dificuldade ocorre ao representar uma imagem na memória de nosso computador, que nada mais é do que uma sequência de bits. Depois disso, ainda precisamos saber como processar esses dados para manipular a imagem e extrair informações.
Tradicionalmente, representamos uma imagem como uma matriz de pixels. Cada pixel corresponde a uma cor ou à intensidade da luz refletida em uma região pequenininha da imagem correspondente ao pixel. Assim, manipular essa imagem nada mais é do que realizar operações sobre essa matriz.
Nesta tarefa, representaremos imagens no formato
PGM, que é utilizado para
armazenar imagens em escala de cinza sem compressão de dados em um
arquivo de texto. Nesse formato, uma imagem é uma matriz de inteiros
no intervalo
O formato PGM começa com uma linha com o texto P2
, que representa
uma imagem em escala de cinza. Depois, pode haver um comentário
arbitrário, começando com #
e a próxima linha deve conter dois
números representando, respectivamente, a largura e a altura da
matriz. Na próxima linha há o número
[Arquivo content/tarefas/07-calculadora-imagens/mc102.pgm não existe]
Calculadora de imagens
Sua tarefa é construir um programa interativo calculadora_imagens.py
capaz de carregar imagens de arquivos PGM da pasta dados
, realizar operações sobre
elas e gravar uma imagem resultante em um novo arquivo dentro da pasta
teste
. O programa mantém em memória um banco de imagens, cada uma
identificada por um índice inteiro começando em
Entrada
Cada linha da entrada conterá o nome de uma operação a ser realizada e
uma sequência de parâmetros correspondentes. Por exemplo, a entrada
abaixo carrega duas fotos na memória. A segunda foto é transformada em
preto e branco utilizando um limiar de
carregar dados/selfie.pgm
carregar dados/disco.pgm
binarizar 1 50
multiplicar 0 1
gravar testes/avatar.pgm 0
A seguir mostramos o que esta acontecendo nos passos anteriores.
carregar selfie.pgm | carregar disco.pgm | binarizar 1 50 | multiplicar 0 1 |
![]() |
![]() |
![]() |
![]() |
Saída
A cada operação processada, deverá ser mostrada uma ou mais linhas na saída, dependendo do comando. A saída para o exemplo acima será.
Carregado arquivo dados/selfie.pgm em imagem 0.
Carregado arquivo dados/disco.pgm em imagem 1.
Imagem 1 modificada: 24244 pixels maiores que zero.
Imagem 0 modificada: 24244 pixels maiores que zero.
Gravado arquivo testes/avatar.pgm com imagem 0.
Operações pixel a pixel
Podemos realizar operações entre duas imagens pixel por pixel. Por exemplo, se multiplicamos as intensidades de duas imagens, alguns pixels terão a intensidade aumentada e outros, diminuída. Podemos usar essa operação para destacar determinadas regiões de uma imagem e esconder as demais. Também podemos realizar operações lógicas, como OR, AND, XOR, SUB. Elas servem como instrumento para extração de componentes da imagem, descrever formas de uma região, como fronteiras, esqueletos e fecho convexo.
Normalizar
Às vezes uma imagem pode estar muito escura porque todos os pixels são
menores que 255; ou muito clara, porque todos os pixels são maiores
que 0. Para ajustar o branco e o preto, podemos normalizar os valores
dos pixels de uma imagem
Entrada
carregar dog.pgm
normalizar <id imagem a>
Saída
Imagem <id imagem a> modificada: xx pixels maiores que zero.
Binarizar
Dado um limiar, defina como 0
todos pixels com valor menor ou igual
ao limiar e como 255
os demais.
Entrada
binarizar <id imagem> <limiar>
Saída
Imagem <id imagem> modificada: xx pixels maiores que zero.
carregar impressao.pgm | binarizar 0 91 |
![]() |
![]() |
Multiplicar
Dadas duas imagens com as mesmas dimensões, modifique a primeira de
forma que o novo pixel tenha o produto dos pixels correspondentes nas
imagens originais. Repare que a imagem resultante pode ter pixels com
intensidades maiores do que
Entrada
carregar dog.pgm
carregar mascara3.pgm
multiplicar <id imagem a> <id imagem b>
Saída
Imagem <id imagem a> modificada: xx pixels maiores que zero.
carregar dog.pgm | mascara3.pgm | multiplicar 0 1 |
![]() |
![]() |
![]() |
Somar
Computa a média dos pixels de duas matrizes de mesma dimensão, descartando a fração não inteira.
Entrada
somar <id imagem a> <id imagem b>
Saída
Imagem <id imagem a> modificada: xx pixels maiores que zero.
carregar dog.pgm | carregar eiffel.pgm | somar 0 1 |
![]() |
![]() |
![]() |
Operações lógicas
Realiza operações lógicas pixel por pixel entre duas imagens com a
mesma dimensão e altera a primeira. Nessas operações, garantimos que
todo pixel tem valor 0
ou 255
, representando verdadeiro e
falso, respectivamente.
Entrada
<OPERADOR> <id imagem a> <id imagem b>
O nome do comando OR
, AND
, XOR
, SUB
.
Saída
Imagem <id imagem a> modificada: xx pixels maiores que zero.

Filtros em imagens
Uma operação comum em imagens é a aplicação de filtros digitais. Abaixo, aplicamos diferentes filtros em uma imagem de exemplo, cada um com um objetivo.

suavização de imagem | remover ruído | melhorar a imagem | destacar bordas |
![]() |
![]() |
![]() |
![]() |
Para aplicar um filtros, realizamos uma operação chamada convolução, que consiste em percorrer a matriz original sobrepondo cada pixel com uma matriz menor (chamada filtro ou kernel). Para computar o valor resultante em cada pixel, multiplicamos os pixels sobrepostos e somamos.
Suponha que o kernel seja a matriz à esquerda, enquanto a matriz à direita seja uma parte da imagem, representando os valores dos pixels. Neste momento, estamos calculando o pixel da posição cujo valor na imagem original é 25. O valor deste pixel na imagem com filtro, após a convolução, será
Quando realizamos esse procedimento em todos os pixels da imagem, temos a imagem filtrada.
A imagem filtrada deve substituir a imagem. Repare que não é possível aplicar o filtro nos pixels próximos da borda da imagem, quando o kernel não couber completamente sobre a imagem. Nesses casos, defina o pixel da imagem filtrada como preto.
Entrada
fitrar <id> <nome do filtro>
O <nome do filtro>
define qual o kernel será utilizado. Você precisa
implementar pelo menos o kernel Laplaciano
(para detectar bordas).
dado pela matriz Gaussiano
(para
suavizado), dado pela matriz
Saída
Imagem <id> modificada: xx pixels maiores que zero.
Dicas
-
Pode ser útil olhar para a imagem em um visualizador. Em distribuições GNU/Linux, a maioria dos visualizadores pode abrir arquivos PBM facilmente. Em outros sistemas operacionais, você talvez precise instalar um visualizador ou editor de imagens, ou pode usar uma ferramenta de conversão online, como essa. Se seu visualizador não funcionar, você tentar fazer download desse.
-
Vocês também podem visualizar uma imagem PBM ou PGM pequena com ferramentas online, e.g., NetpbmViewer.
-
Não tente fazer tudo de uma vez. Sempre escreva cada um dos algoritmos com calma antes de programá-lo. Experimente começar se preocupando com a leitura da entrada e saída. Pesquise sobre como ler todas as linhas da entrada padrão. Por exemplo, se você tentar ler uma linha quando a entrada já acabou, ocorrerá uma exceção. Reveja os exercícios da lista 5 para relembrar como tratar exceções.
Critérios
Para obter conceito B
é obrigatório implementar pelo menos os
comandos carregar, gravar, binarizar, normalizar, multiplicar e
aplicar o filtro laplaciano. Para obter conceito A
, implemente
também as operações lógicas AND e SUB.
Correção
Esta tarefa será corrigida automaticamente sempre que você realizar um
git push
. Depois de terminada a tarefa, deve-se utilizar o botão na
interface de notas para solicitar a correção de um monitor.