PUCRS/FACIN
Curso de Especialização em Desenvolvimento de Jogos Digitais


Computação Gráfica 2D


Profs.
    Márcio Sarroglia Pinho
    Isabel Harb Manssour
   

Processamento de Imagens



O objetivo desta aula é permitir que se rastreie o movimento de um objeto em uma imagem de vídeo.

 

Tela0.png

Tela1.png

Tela2.png

 

Figura – Exemplo de Frames de Vídeo

 

No exemplo apresentado nesta aula as imagens são obtidas a partir de um vídeo carregado com a biblioteca AVIClass.

Esta biblioteca utiliza duas outras bibliotecas, uma para carregar o vídeo de disco e outra para permitir o processamento de cada frame deste vídeo.

Para carregar o vídeo de disco é utilizada a biblioteca IM, desenvolvida no TecGraf da  PUC-Rio.

Para permitir o acesso aos pixels de cada frame do vídeo e assim prossibilitar que se processe a imagem é utilizada a biblioteca ImageClass, desenvolvida no Grupo de Realidade Virtual da PUCRS.

 

A exibição de cada frame na tela é feita em OpenGL.

 

Carga do Vídeo

 

Copie e descompacte o arquivo ProcImagem.zip. Abra o projeto ImagensOpenGL.sln no Visual Studio 8 e execute-o. Isto deve exibir o video na tela. Durante a exibição, pressione a tela C e veja a conversão do vídeo para tons de cinza.

 

Abra o fonte AVITest-THREE.cpp e observe o funcionamento da função init. Ela é a responsável pela carga da imagem. O objeto Video utilizado na função é um objeto da classe AVIClass.

 

void init(void)

{

cout << "Init..." ;

    glClearColor(0.0f, 0.0f, 1.0f, 1.0f); // Fundo de tela preto

     

    // define quais os formatos de vídeo deverão ser usados pelo programa

    imFormatRegisterAVI();

    imFormatRegisterWMV();

    //if(Video.openVideoFile("3KM.avi") == 0)

    if(Video.openVideoFile("video31.wmv") == 0)

    {

        cout << "Video nao existe. Pressione ENTER para encerrar." << endl;

        getchar();

        exit (0);

    }

    cout << "Nro de Frames:" << Video.getTotalFrames() << endl;

    cout << "Fim." << endl;

 

}

 

 

Observe o método display. Ele é o responsável pela obtenção de cada frame do arquivo de vídeo e pela exibição deste frame em OpenGL.

 

void display( void )

{

     

      int loadFrameOK;

      float ZoomH, ZoomV;

 

      glClear(GL_COLOR_BUFFER_BIT);

 

      glMatrixMode(GL_PROJECTION);

      glLoadIdentity();

      glOrtho(-10,10,-10,10,-1,1);

 

      glMatrixMode (GL_MODELVIEW);

      glLoadIdentity();

 

      loadFrameOK = Video.loadImageFrame(frame);

      // avança o nro do frame

      frame ++;

      cout << "Frame: " << frame << endl;

      // se atingiu o final do vídeo, então recomeça

      if (frame == Video.getTotalFrames())

      {

             frame = 0;

            // getchar();

             return;

      }

 

      if (loadFrameOK) // se o frame foi corretamente carregado

      {

       

        // cout << "Imagem Exibida !!" << endl;

         Video.SetPos(-10,-10);

         // acerta o zoom da imagem para que ocupe toda a janela

         CalculaNivelDeZoom(ZoomH, ZoomV);

         Video.SetZoomH(ZoomH);

         Video.SetZoomV(ZoomV);

         if (cinza) // se o usuário solicitou a exeibição em tons de cinza

              ConverteCinza(Video);

 

         Video.Display();

      }

      else cout << "Erro..." << endl;

 

      glutSwapBuffers();

}

 

Processamento dos Frames

 

Um frame de vídeo é tratado pela AVIClass como sendo uma matriz na qual cada entrada corresponde a um pixel do frame. Para obter detalhes do métodos de acesso aos pixels, veja a página da classe ImageClass, da qual a AVIClass é derivada.

 

Observe a função ConverteCinza que é ser ativada quando o usuário pressiona a tecla “C“ durante a exibição do vídeo.

 

// **********************************************************************

//  void ConverteCinza(ImageClass *Img)

// **********************************************************************

void ConverteCinza(AVIClass V)

{

    int x,y;

    int i;

    unsigned char r,g,b;

    for(y=0;y<V.SizeY();y++)

    {

        for(x=0;x<V.SizeX();x++)

        {

            i = V.GetPointIntensity(x,y);

            V.DrawPixel(x, y,i,i,i);

        }

    }

}

Esta função troca a cor R,G,B de cada pixel da imagem por sua intensidade de cinza.

 

 

Crie uma nova função que mude a cor dos pixels do frame nos pontos em que a quantidade de vermelho do pixel for maior que u certo valor.

Para ler a cor de um pixel da imagem utilize o método ReadPixel. Use o exemplo abaixo e veja o resultado.

 

void SelecionaVermelho(AVIClass *V)

{

    int x,y;

    unsigned char r,g,b;

    for(y=0;y<V->SizeY();y++)

    {

        for(x=0;x<V->SizeX();x++)

        {

            V->ReadPixel(x,y, r,g,b);

            if (r > 200)

                        V->DrawPixel(x, y,0,0,0);

                  else V->DrawPixel(x, y,255, 255, 255);

        }

    }

}

 

Altere o código de forma a separar apenas a etiqueta vermelha.

 

Calcule o centro da região da etiqueta vermelha e exiba-o como um cursor em forma de cruz. Para desenhar sobre a imagem utilize o métodos DrawLineH, DrawLineV da ImageClass.

 

Trace a trajetória do movimento da etiqueta.


FIM.