quinta-feira, 20 de junho de 2013

Manipulação de imagens no processing

Olá pessoas!

Hoje vamos falar sobre manipulação de imagens com o Processing.
Uma imagem pode ser entendida como uma matriz de valores que guardam dados referentes a cor do pixel.
Vamos mostrar um algoritmo que tem como propósito inverter as tonalidades de uma imagem, ou seja, aplicar o filtro negativo.

O código segue na imagem abaixo (click nela para ampliar):


Bem, para poder manipular uma imagem você deverá criar um atributo do tipo PImage, que tem como função carregar os pixels da imagem para podermos manipular. Após criar o atributo PImage, temos diponíveis algum métodos legais, como:
  • pixels[]: retorna um vetor contem do os valores referentes a cor analisada.
  • get(i,j): retorna o valor referente a cor em detarminada posição na matriz da imagem.
  • set(i,j,valor): permite que a gente possa atribuir um valor para uma cor em determinada posição.
O algoritmo consiste em descobrir qual o maior valor de cor e fazer a diferença dele com os outros valores da imagem. Para isso foi criada uma função chamada maiorElementoVetor[], que retorna o maior valor do vetor de cores.
Percorremos cada pixel da imagem substituindo o pixel analisado pelo resultado da subtração do maior pixel pelo pixel analisado.

Abaixo um exemplo que ilustra o resultado:

Antes

Depois

Well, that's all folks!! :)

segunda-feira, 13 de maio de 2013

Aplicando convolução ao Som

Hi peoples!

No segundo post sobre nossa jornada pelo processing e universo multimídia vamos brincar um pouco com uma técnica que tem como propósito a implementação de filtros para sons ou imagens. A técnica , que por enquanto vamos explorar em som, chama-se convolução.
Trata-se de um processo de aplicação de efeitos em áudio, onde podemos considerar o som como um vetor de números e vamos alterar esses valores para aplicar um efeito que desejamos. Essa alteração sedá pela multiplicação dos valores do vetor do som por uma matriz que contém uma representação discreta de uma curva gaussiana. A curva gaussiana tem um formato similar ao de um sino e é utilizada em vários campos da matemática, física.. Para saber mais sobre as propriedades dessa entidade matemática sugiro dar uma olhadinha na nossa querida enciclopédia livre: wikipédia.

Abaixo segue o código do programinha desenvolvido para ilustrar essa tal de convolução:

import ddf.minim.*;
import ddf.minim.analysis.*;
import javax.sound.sampled.*;

Minim minim;
AudioSample audio;

AudioSample filtroPassaBaixa;
AudioSample filtroBox;
AudioSample filtroPassaAlta;


float[] out;

void setup(){
  size(500,600);
 
  AudioFormat formatoAudio = new AudioFormat(44100,16,2,true,true);
 
  minim = new Minim(this);
 
  float[] passaAlta = {0.1, 0.8, 1 ,0.8,0.1};
  float[] matrizBox = {1, 1, 1 ,1,1};
  float[] passaBaixa = {0.9, 0.2, 0 ,0.2, 0.9};
 
  audio = minim.loadSample("/home/gleison/musica.mp3", 1024);
  out = audio.getChannel(AudioSample.RIGHT);
 
  float[] outPassaAlta = convolucao(out, passaAlta);
  float[] outFiltroBox = convolucao(out, matrizBox);
  float[] outPassaBaixa = convolucao(out, passaBaixa);
 
  filtroPassaAlta = minim.createSample(outPassaAlta, formatoAudio);
  filtroPassaAlta.trigger();
 
  filtroBox = minim.createSample(outFiltroBox, formatoAudio);
  filtroBox.trigger();
 
  filtroPassaBaixa = minim.createSample(outPassaBaixa, formatoAudio);
  filtroPassaBaixa.trigger();

}

float[] convolucao(float[] input, float[] matrizConvolucao){
  float[] out = new float[input.length];
 
  for(int i = 0; i < input.length - matrizConvolucao.length; i++){
    float soma = 0;
   
    for(int j = 0; j < matrizConvolucao.length; j++){
      soma += input[i + j] * matrizConvolucao[j];
    }
    out[i] = soma;
  }
  return out;
}

void draw(){
  background(0);
  stroke(255);
 
  for(int i = 0; i < filtroPassaAlta.mix.size() - 1; i++){
    line(i, 100 + filtroPassaAlta.mix.get(i)*30, i+1, 100 + filtroPassaAlta.mix.get(i+1)*30);
  }
 
  for(int i = 0; i < filtroBox.mix.size() - 1; i++){
    line(i, 250 + filtroBox.mix.get(i)*30, i+1, 250 + filtroBox.mix.get(i+1)*30);
  }
 
  for(int i = 0; i < filtroPassaBaixa.mix.size() - 1; i++){
    line(i, 400 + filtroPassaBaixa.mix.get(i)*30, i+1, 400 + filtroPassaBaixa.mix.get(i+1)*30);
  }

}

Bem, acho que o código é relativamente simples de entender, por isso vou focar apenas na função denominada convolução. Ela recebe como parâmetro o vetor que representa o áudio que vamos manipular e a matriz que contém os valores gaussianos. Seu retorno é um vetor onde cada posição contém o valor da somatória do produto dos valores da matriz gaussiana pelo vetor do áudio.

Na função draw fizemos um método simples, pescado da documentação, para mostrar a ocilação do som e fazermos uma comparação.

Abaixo segue um print da aplicação:






E para detalhes sobre a biblioteca minim que utilizamos é ś dar uma olhada na documentação: http://code.compartmental.net/tools/minim/.

E é isso.

That's all folks!

segunda-feira, 29 de abril de 2013

Introdução ao Processing

Olá pessoas!

Hoje vamos inaugurar o blog com uma breve introdução à linguagem Processing.org.
Processing é uma linguagem OpenSource (código-fonte aberto) que abstrai algumas operações sobre objetos multimídia (vídeo, áudio e imagens). É de fácil aprendizagem e tem uma boa documentação, que pode ser encontrada no próprio site do Processing (http://processing.org/).
Processing também possui um ambiente de programação próprio, onde faremos nossos experimentos e projetos.

Tela inicial do ambiente de programação do Processing.

Vamos começar com o bê-a-bá do Processing, desenharemos algumas formas geométricas simples: linhas, elipses e retângulos. Para manipular objetos gráficos temos que utilizar as coordenadas x, y e z para localizá-los na tela do aplicativo.
O primeiro comando que utilizaremos é o comando line(), responsável por desenhar linhas na tela. Esse comando recebe quatro parâmetros (x1, y1, x2, y2), onde x1 e y1 definem a coordenada da tela onde começa a linha e o par (x2, y2) indicam onde termina. Vamos fazer um exemplo para ilustrar: digite no editor do Processing o comando line(0,0,50,50);. O resultado será o da tela abaixo:
De forma semenhante vamos criar um quadrado e uma elipse. Para criar um quadrilátero temos que usar o comando rect() passando como parâmetros as coordenadas do canto inferior-esquerdo e do canto superior-direito. Digite no editor o comando: rect(0,0,80,80);, o resultado será semelhante ao mostrado abaixo:

Para desenhar uma elipse  devemos passar sua posição(x, y), largura e altura como parâmetros. Digitando o comando ellipse(50,50,40,30); você obterá o seguinte resultado:




Você deve ter notado que nossas imagens até agora estão sem cor de preenchimento ou contorno. Vamos agora adicionar essas propriedades ao nosso desenho. Também alteraremos o tamanho da nossa janela de exibição. 
O comando que controlam o tamanho da janela é o size(). Esse comando recebe como parâmetro as dimenções na janela em pixels. Nós definimos a cor de preenchimento da janela com o comando background(), que recebe como parâmetros três números entre 0 e 255 que representam a cor no padrão RGB. 
Os comandos size() e background() devem ficar dentro da função setup() (função responsável por iniciar as propriedades do desenho).
Os comandos relacionados  ao desenho dos objetos na tela devem ficar dentro da função draw(). Abaixo ilustramos o exemplo do desenho da elipse com suas propriedades alteradas.


Agora vamos fazer uma aplicação contendo recursos de animação, onde capturaremos as posições do mouse por meio das contantes mouseX e mouseY para desenharmos circulos coloridos quando apertamos o botão esquerdo do mouse. Para identificarmos quando o mouse é pressionado utilizaremos o comando mousePressed(). Com o auxílio da função random() faremos cores aleatórias. Digite no editor o seguinte programa:

void setup(){
         size(500,500);
         background(45,67,78);
}

void draw(){
        if(mousePressed){
              ellipse(mouseX, mouseY, 40, 40);
        }

        fill(random(0,255), random(0,255), random(0,255));
}


O resultado será semelhante ao da figura a seguir:




Enfim, por hoje é só, mas continuaremos com nossas experiências com Processing.

That's all folks!!

Referências:

http://processing.org/