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.
|
|
|
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.