Transformações em Imagens Matriciais
Links relacionados: Computação Gráfica
Introdução
Qualquer imagem matricial (jpg, png, etc.) pode ser utilizada para testar os algoritmos e códigos de exemplos fornecidos neste material.
Cor
A cor é composta de 3 componentes: o vermelho, o verde e o azul. É comum identificar a cor pelos elementos RGB (iniciais do inglês referentes às componentes de cor Red, Gree, Blue).
O código a seguir apresenta uma definição de classe referente a Cor, com seus três componentes básicos
1class Cor {
2 int vermelho;
3 int verde;
4 int azul;
5}
Filtrando uma Única Cor
Em uma imagem matricial, podemos filtrar uma única cor do conjunto de cores RGB. Neste algoritmo de exemplo, estamos apenas pegando a cor vermelha da imagem.
imagemOrigem
imagemDestino
Para y = 0; até imagemOrigem.altura fazer
Para x = 0 até imagemOrigem.largura fazer
cor = pegarPixel(imagemOrigem, x, y)
cor.verde = 0
cor.azul = 0
pintarPixel(imagemDestino, x, y, cor)
Fim para
Fim para
Abaixo encontra-se o código em C++ utilizando a biblioteca SFML do exemplo acima:
1#include <SFML/Graphics.hpp>
2#include <iostream>
3#include <fstream>
4
5using namespace std;
6
7int main(int argc, char *argv[])
8{
9 string arquivo = argv[1];
10 sf::Image img;
11 if (!img.LoadFromFile(arquivo))
12 {
13 cout << "Erro ao abrir o arquivo " << arquivo << endl;
14 return -1;
15 }
16 sf::Image out(img.GetWidth(), img.GetHeight());
17 for (unsigned int y = 0; y < img.GetHeight(); y++)
18 {
19 for (unsigned int x = 0; x < img.GetWidth(); x++)
20 {
21 sf::Color cor = img.GetPixel(x, y);
22 out.SetPixel(x, y, sf::Color(cor.r, 0, 0));
23 }
24 }
25 string arquivoSaida = argv[2];
26 if (!out.SaveToFile(arquivoSaida))
27 {
28 cout << "Erro ao salvar arquivo " << arquivoSaida << endl;
29 return -2;
30 }
31}
Alterando o Tamanho de uma Imagem
Uma imagem pode ser redimensionada, gerando uma nova imagem de tamanho diferente da original. No exemplo a seguir, a imagem é reduzida para sua metade (50%), tanto em largura como em sua altura.
escala = 50 imagemOrigem imagemDestino largura = imagemOriginal.largura * (escala / 100) altura = imagemOriginal.altura * (escala / 100) imagemDestino.tamanho(largura, altura) Para y = 0 até altura fazer yaux = y * imagemOriginal.altura / altura Para x = 0 até largura fazer xaux = x * imagemOriginal.largura / largura cor = pegarPixel(imagemOrigem, xaux, yaux) pintarPixel(imagemDestino, x, y, cor) Fim para Fim para
A seguir se encontra o código em C++ do algoritmo.
1#include <SFML/Graphics.hpp>
2#include <iostream>
3#include <fstream>
4
5using namespace std;
6
7int main(int argc, char *argv[])
8{
9 string origem = argv[1];
10 string destino = argv[2];
11 int escala = atoi(argv[3]);
12
13 sf::Image orig;
14 if (!orig.LoadFromFile(origem))
15 {
16 cout << "Erro ao abrir o arquivo " << origem << endl;
17 return -1;
18 }
19 int largura = (int) (orig.GetWidth() * (escala / 100.0));
20 int altura = (int) (orig.GetHeight() * (escala / 100.0));
21 sf::Image dest(largura, altura);
22 for (int y = 0; y < altura; y++)
23 {
24 int yaux = y * orig.GetHeight() / altura;
25 for (int x = 0; x < largura; x++)
26 {
27 int xaux = x * orig.GetWidth() / largura;
28 sf::Color cor = orig.GetPixel(xaux, yaux);
29 dest.SetPixel(x, y, cor);
30 }
31 }
32 if (!dest.SaveToFile(destino))
33 {
34 cout << "Erro ao salvar arquivo " << destino << endl;
35 return -2;
36 }
37}
Line Art
Para criar o efeito de Line Art de uma imagem, pode-se primeiramente transformar as cores da imagem em tons de cinza e, depois modificar suas cores. Neste exemplo, caso a cor resultante for menor que 127, então a cor se transformará em 0 (preto), senão ela se transformará em 255 (branco).
imagemOrigem
imagemDestino
Para y = 0; até imagemOrigem.altura fazer
Para x = 0 até imagemOrigem.largura fazer
cor = cinza(pegarPixel(imagemOrigem, x, y))
Se cor < 127 então
cor = 0
senão
cor = 255
pintarPixel(imagemDestino, x, y, cor);
Fim para
Fim para
A seguir se encontra o código em C++ do algoritmo.
1#include <SFML/Graphics.hpp>
2#include <iostream>
3#include <fstream>
4
5using namespace std;
6
7int tomCinza(sf::Color cor)
8{
9 return (int) ((0.299 * cor.r) + (0.587 * cor.g) + (0.114 * cor.b));
10}
11
12int main(int argc, char *argv[])
13{
14 string origem = argv[1];
15 string destino = argv[2];
16
17 sf::Image orig;
18 if (!orig.LoadFromFile(origem))
19 {
20 cout << "Erro ao abrir o arquivo " << origem << endl;
21 return -1;
22 }
23 sf::Image dest(orig.GetWidth(), orig.GetHeight());
24 for (unsigned int y = 0; y < orig.GetHeight(); y++)
25 {
26 for (unsigned int x = 0; x < orig.GetWidth(); x++)
27 {
28 int cinza = tomCinza(orig.GetPixel(x, y));
29 int cor = 255;
30 if (cinza < 127)
31 {
32 cor = 0;
33 }
34 dest.SetPixel(x, y, sf::Color(cor, cor, cor));
35 }
36 }
37 if (!dest.SaveToFile(destino))
38 {
39 cout << "Erro ao salvar arquivo " << destino << endl;
40 return -2;
41 }
42 return 0;
43}
Detecção de Bordas
O algoritmo de filtro a seguir é proposto para detectar boradas em imagens, baseado no algoritmo de detecção de bordas de Zambiasi (2005). Este algoritmo transforma a imagem em lineart e compara se seus pixeis (x,y) são diferentes dos pixeis (x+1, y+1).
imagemOrigem
imagemDestino
Para y = 0; até imagemOrigem.altura fazer
Para x = 0 até imagemOrigem.largura fazer
corA = lineart(pegarPixel(imagemOrigem, x, y);
corA = lineart(pegarPixel(imagemOrigem, x+1, y+1);
se corA = corB então
cor = 255;
senao
cor = 0;
pintarPixel(imagemDestino, x, y, cor);
Fim para
Fim para
A seguir se encontra o código em C++ do algoritmo.
1#include <SFML/Graphics.hpp>
2#include <iostream>
3#include <fstream>
4
5using namespace std;
6
7int lineArt(sf::Color cor)
8{
9 int cinza = (int) ((0.299 * cor.r) + (0.587 * cor.g) + (0.114 * cor.b));
10 if (cinza < 127)
11 {
12 return 0;
13 }
14 return 1;
15}
16
17int main(int argc, char *argv[])
18{
19 string origem = argv[1];
20 string destino = argv[2];
21
22 sf::Image orig;
23 if (!orig.LoadFromFile(origem))
24 {
25 cout << "Erro ao abrir o arquivo " << origem << endl;
26 return -1;
27 }
28 sf::Image dest(orig.GetWidth(), orig.GetHeight());
29 for (unsigned int y = 0; y < orig.GetHeight() - 1; y++)
30 {
31 for (unsigned int x = 0; x < orig.GetWidth() - 1; x++)
32 {
33 int corA = lineArt(orig.GetPixel(x, y));
34 int corB = lineArt(orig.GetPixel(x + 1, y + 1));
35 int cor = 0;
36 if (corA == corB)
37 {
38 cor = 255;
39 }
40 dest.SetPixel(x, y, sf::Color(cor, cor, cor));
41 }
42 }
43 if (!dest.SaveToFile(destino))
44 {
45 cout << "Erro ao salvar arquivo " << destino << endl;
46 return -2;
47 }
48 return 0;
49}