Transformações em Imagens Matriciais

De Aulas
Revisão de 17h57min de 9 de abril de 2018 por Admin (discussão | contribs) (→‎Alterando o Tamanho de uma Imagem)
(dif) ← Edição anterior | Revisão atual (dif) | Versão posterior → (dif)

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.

Figura 1. Imagem Original.

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
Figura 2. Somente com a componente cor vermelha.

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
Figura 3.Metade do tamanho da imagem original.

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
Figura 4.Line Art.

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
Figura 5.Algoritmo de detecção de bordas.

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}