Manipulação de imagens no formato PPM
O artigo seguinte faz uma introdução sobre o formato ".ppm", que faz o armazenamento de forma simples e "bruta" de imagens. Além de como manipular o arquivo, para podermos aplicar filtros de imagem já existentes ou criar nossos próprios filtros.
Parte 3: Filtros
Agora chegamos na parte interessante deste artigo, criar filtros para as imagens. O seu propósito final pode variar, de como entender como os filtros que aplicamos no Instagram e outros programas funcionam, passando por inserção de logo ou marca em imagens de forma automatizada, até testar o resultado de seu próprio filtro.
Vou dar exemplos de filtros simples, porém é bom saber que temos como aplicar qualquer tipo em uma imagem, o limite é a nossa criatividade.
Começaremos com um filtro que transforma uma imagem colorida em uma imagem com tons de cinza, famoso "B&W" ou em português, branco e preto, que na verdade é chamado assim incorretamente. Para converter qualquer cor em seu nível aproximado de cinza, deve-se primeiro obter suas primitivas vermelho, verde e azul (da escala RGB). Adiciona-se então 30% do vermelho mais 59% do verde mais 11% do azul, independente da escala utilizada (0.0 a 1.0, 0 a 255, 0% a 100%.). No código serão valores com melhor precisão, para não escaparem cores fracas.
O código em si é bem simples, apenas calcula a regra mostrada anteriormente e depois distribui para todos três componentes dos pixeis. E também confere, caso no calculo, algum dos pixeis acabem passando de 255.
O segundo filtro será o filtro de auto relevo, que é usado para fazer macas d'água em papéis e outros tipos de materiais timbrados. Para o calculo dele, pegamos uma variável qualquer e subtraímos de sua variável de posição oposta, e este valor substitui a central, escolhi fazer isso com as variáveis das linhas anteriores e posteriores, mas poderia ser feito com as da lateral, ou até mesmo diagonal.
O cálculo é de forma simples de se explicar feito sobre esta matriz:
E por último aplicaremos o espelhamento, que é nada mais que inverter a imagem.
Esse efeito é bem simples, ele apenas substitui o pixel atual pelo pixel de complemento, ou seja, pega a dimensão da imagem, e subtrai dela o pixel corrente, para encontrar seu correspondente no outro lado da imagem. Neste caso o espelhamento foi feito na horizontal, mas nada impede de faze-lo na vertical, ou alterar a fórmula para girar a imagem.
Além destes, podemos obter muitos outros efeitos em fotos, como blur motion, sépia, detecção de bordas, negativo... O limite será sua necessidade e/ou criatividade.
Qualquer dúvida ou sugestão me disponibilizo no email abaixo, segue também o arquivo do algoritmo completo. E lembre-se, ao invés de ser apenas um usuário, seja um proliferador da informação, abraço.
pablo_margreff@hotmail.com
Fontes:
Vou dar exemplos de filtros simples, porém é bom saber que temos como aplicar qualquer tipo em uma imagem, o limite é a nossa criatividade.
Começaremos com um filtro que transforma uma imagem colorida em uma imagem com tons de cinza, famoso "B&W" ou em português, branco e preto, que na verdade é chamado assim incorretamente. Para converter qualquer cor em seu nível aproximado de cinza, deve-se primeiro obter suas primitivas vermelho, verde e azul (da escala RGB). Adiciona-se então 30% do vermelho mais 59% do verde mais 11% do azul, independente da escala utilizada (0.0 a 1.0, 0 a 255, 0% a 100%.). No código serão valores com melhor precisão, para não escaparem cores fracas.
void gray_scale(pixel imagem[MAX][MAX], int coluna, int linha) {
int i, j;
for (i = 0; i < linha; i++){
for (j = 0; j < coluna; j++){
imagem[i][j].r = (int) ((0.299 * imagem[i][j].r) + (0.587 * imagem[i][j].g) + (0.144 * imagem[i][j].b)); //calcula o valor para conversão
imagem[i][j].g = imagem[i][j].r; //copia o valor para
imagem[i][j].b = imagem[i][j].r; //todas componentes
//testa o valor para ver se o mesmo não passou de 255
if (imagem[i][j].r > 255){
imagem[i][j].r = 255;
imagem[i][j].g = 255;
imagem[i][j].b = 255;
}
}
}
}
O código em si é bem simples, apenas calcula a regra mostrada anteriormente e depois distribui para todos três componentes dos pixeis. E também confere, caso no calculo, algum dos pixeis acabem passando de 255.
O segundo filtro será o filtro de auto relevo, que é usado para fazer macas d'água em papéis e outros tipos de materiais timbrados. Para o calculo dele, pegamos uma variável qualquer e subtraímos de sua variável de posição oposta, e este valor substitui a central, escolhi fazer isso com as variáveis das linhas anteriores e posteriores, mas poderia ser feito com as da lateral, ou até mesmo diagonal.
void autorelevo(pixel imagem[MAX][MAX], int coluna, int linha) {
pixel img[linha][coluna]; // cria uma imagem para salvar o resultado do emboss
int i, j;
for (i = 1; i < linha - 1; i++){
for (j = 0; j < coluna; j++){
img[i][j].r = imagem[i + 1][j].r - imagem[i -1][j].r; //faz a operação passando o
img[i][j].g = imagem[i + 1][j].b - imagem[i -1][j].b; //resultado para a matriz de
img[i][j].b = imagem[i + 1][j].b - imagem[i -1][j].b; //backup
if (img[i][j].r < 0) //testa os limites
img[i][j].r = 0;
if (img[i][j].g < 0)
img[i][j].g = 0;
if (img[i][j].b < 0)
img[i][j].b = 0;
}
}
for (i = 1; i < linha - 1; i++){
for(j = 0; j < coluna; j++){
imagem[i][j].r = img[i][j].r + 128; //adiciona 128 para clarear a imagem
imagem[i][j].g = img[i][j].g + 128;
imagem[i][j].b = img[i][j].b + 128;
if (img[i][j].r > 255) //testa os limites
img[i][j].r = 255;
if (img[i][j].g > 255)
img[i][j].g = 255;
if (img[i][j].b > 255)
img[i][j].b = 255;
}
}
}
O cálculo é de forma simples de se explicar feito sobre esta matriz:
0 -1 0 0 C 0 0 1 0Onde o pixel central é substituído pela soma do negativo imediatamente acima, e o valor positivo imediatamente abaixo, depois testamos os limites. Lembrando que usamos uma matriz para guardar os resultados, já que se alterarmos o valor imediatamente após realizarmos a conta, haveria interferência, pois usamos os pixeis para calcular os da próxima linha. Depois que tudo é calculado a matriz resposta é passada para a matriz original.
E por último aplicaremos o espelhamento, que é nada mais que inverter a imagem.
void espelhar(pixel imagem[MAX][MAX], int coluna, int linha) {
pixel img[linha][coluna];
int i, j;
for (i = 0; i < linha; i++) {
for (j = 0; j < coluna; j++) {
img[i][j].r = imagem[i][coluna - j].r; //salva em uma matriz do tipo pixel a imagem com suas
img[i][j].g = imagem[i][coluna - j].g; //linhas salvas em complementos, isso faz com que a imagem
img[i][j].b = imagem[i][coluna - j].b; //pegue o pixel complementar no seu extremo oposto horizontal
}
}
//passa a imagem para a matriz original
for (i = 0; i < linha; i++) {
for (j = 0; j < coluna; j++) {
imagem[i][j].r = img[i][j].r;
imagem[i][j].g = img[i][j].g;
imagem[i][j].b = img[i][j].b;
}
}
}
Esse efeito é bem simples, ele apenas substitui o pixel atual pelo pixel de complemento, ou seja, pega a dimensão da imagem, e subtrai dela o pixel corrente, para encontrar seu correspondente no outro lado da imagem. Neste caso o espelhamento foi feito na horizontal, mas nada impede de faze-lo na vertical, ou alterar a fórmula para girar a imagem.
Além destes, podemos obter muitos outros efeitos em fotos, como blur motion, sépia, detecção de bordas, negativo... O limite será sua necessidade e/ou criatividade.
Qualquer dúvida ou sugestão me disponibilizo no email abaixo, segue também o arquivo do algoritmo completo. E lembre-se, ao invés de ser apenas um usuário, seja um proliferador da informação, abraço.
pablo_margreff@hotmail.com
Fontes:
- Nível de cinza - Wikipédia, a enciclopédia livre
- RGB to Grayscale Conversion Calculator
- Image Filtering - lodev.org