INF01046 – Fundamentos de Processamento de Imagens

 

Prof. Manuel M. Oliveira

Aluno: Lucas Enrique Guaycochea

 

3º Trabalho de Implementação

 

 

 

 

OBJETIVOS

 

O objetivo deste trabalho é ficar familiarizado com conceitos fundamentais como convolução e filtragem no domínio espacial. Ao completár, ficaremos compreendido:

 

a) O conceito de filtros serparáveis e como eles podem ser utilizados para produzir filtros de mais alta ordem;

b) Aumentar (zoom in) e reduzir (zoom out) imagens;

c) Realizar convoluções para obter efeitos como borramento (filtros passa baixas), detecção de bordas (filtros passa altas) e embossing;

d) Rotacionar uma imagem de 90 graus.

 

Nos familiarizaremos com vários kernels úteis e compreenderemos seus efeitos sobre imagens.

 

 

IMPLEMENTAÇÃO

 

Funções feitas pra o programa:

 

·       Zoom out:

 

unsigned char* zoom_out(unsigned char* imagem, int height, int width, int channels, int sx, int sy){

 

            int width_novo=(int)(width/sx);

            float aux=(float)width/sx;

            if (width_novo<aux)

                        width_novo+=1;

            int height_novo=(int)(height/sy);

            aux=(float)height/sy;

            if (height_novo<aux)

                                   height_novo+=1;

            int totalbytes_novos=height*width*channels;

            int bytesFila_novo=width_novo*channels;

 

            unsigned char* resultado=(unsigned char*)malloc(totalbytes_novos*sizeof(unsigned char));

           

            int y=0;

            int i=0;

            while(i<height){

                        int j=0;

                        int x=0;

                        while(j<width){

                                   int R=0;

                                   int G=0;

                                   int B=0;

                                   int ii=i;

                                   int k=0;

                                   while((ii<i+sy)&&(ii<height)){

                                               int jj=j;

                                               while((jj<j+sx)&&(jj<width)){

                                                           R+=imagem[ii*width*channels+jj*channels];

                                                           G+=imagem[ii*width*channels+jj*channels+1];

                                                           B+=imagem[ii*width*channels+jj*channels+2];

                                                           k++;

                                                           jj++;

                                               }

                                               ii++;

                                   }

                                   resultado[y*width_novo*channels+x*channels]=(int)R/k;

                                   resultado[y*width_novo*channels+x*channels+1]=(int)G/k;

                                   resultado[y*width_novo*channels+x*channels+2]=(int)B/k;

                                   x++;

                                   j+=sx;

                        }

                        i+=sy;

                        y++;

            }

            return resultado;

}

 

Como exemplo os seguintes resultados:

 

 

Originales:

 


Zoom out onde sx=2 e sy=2 :

 


 

Zoom out desproporcionais: sx = 3 e sy = 4                                                                                                                     sx = 5 e sy = 3


 

·       Zoom in:

 

unsigned char* zoom_in(unsigned char* imagem, int height, int width, int channels){

            int totalbytes=4*height*width*channels;

            int bytesFila=width*channels;

            int width_novo=2*width;

            int height_novo=2*height;

            unsigned char* resultado=(unsigned char*)malloc(totalbytes*sizeof(unsigned char));

           

            for(int i=0;i<height;i++)

                        for (int j=0;j<width;j++)

                                   for(int k=0;k<channels;k++){

                                               resultado[2*i*width_novo*channels+2*j*channels+k]=imagem[i*bytesFila+j*channels+k];

                                               if(j<width-1)

                                                           resultado[2*i*width_novo*channels+(2*j+1)*channels+k]=(int)((imagem[i*bytesFila+j*channels+k]+imagem[i*bytesFila+(j+1)*channels+k])/2);

                                               else

                                                           resultado[2*i*width_novo*channels+(2*j+1)*channels+k]=imagem[i*bytesFila+j*channels+k];

                                   }

 

            i=1;

            while(i<height_novo){

                        for(int j=0;j<width_novo;j++){

                                   for(int k=0;k<channels;k++)

                                               if (i<height_novo-1)

                                                           resultado[i*width_novo*channels+j*channels+k]=(int)((resultado[(i-1)*width_novo*channels+j*channels+k]+resultado[(i+1)*width_novo*channels+j*channels+k])/2);

                                               else

                                                           resultado[i*width_novo*channels+j*channels+k]=resultado[(i-1)*width_novo*channels+j*channels+k];

                        }

           

                        i+=2;

            }

 

            return resultado;

 

}

 

 

Os resultados podem-se olhar aquí:

 


 

 

·       Rotação horaria::

 

unsigned char* rotar_horario(unsigned char* imagem, int height, int width, int channels){

            int totalbytes=height*width*channels;

            int bytesFila=width*channels;

            int width_novo=height;

            int height_novo=width;

            unsigned char* resultado=(unsigned char*)malloc(totalbytes*sizeof(unsigned char));

           

            for(int i=0;i<height;i++)

                        for (int j=0;j<width;j++)

                                   for(int k=0;k<channels;k++)

                                               resultado[(j+1)*width_novo*channels-(i+1)*channels+k]=imagem[i*bytesFila+j*channels+k];

 

            return resultado;

}

 

 

Distintos resultados podem-se ver a continuação:

 

 


 

 

 

·       Rotação antihoraria:

 

unsigned char* rotar_antihorario(unsigned char* imagem, int height, int width, int channels){

      int totalbytes=height*width*channels;

      int bytesFila=width*channels;

      int width_novo=height;

      int height_novo=width;

      unsigned char* resultado=(unsigned char*)malloc(totalbytes*sizeof(unsigned char));

     

      for(int i=0;i<height;i++)

                  for (int j=0;j<width;j++)

                             for(int k=0;k<channels;k++)

                                         resultado[totalbytes-(j+1)*width_novo*channels+i*channels+k]=imagem[i*bytesFila+j*channels+k];

                 

      return resultado;

 

}

 

O resultado pode-se ver:

 


 

 

·       Convolução:

 

Finalmente, a função pra a convolução e seus resultados:

 

unsigned char* convolucion(unsigned char* imagem, int height, int width, int channels, float** kernel, int clampping){

            int totalbytes=height*width*channels;

            int bytesFila=width*channels;

           

            unsigned char* resultado=(unsigned char*)malloc(totalbytes*sizeof(unsigned char));

 

            for(int i=0;i<height;i++)

                        for (int j=0;j<width;j++){

                                  

                                   if ((i!=0)&&(i!=height-1)&&(j!=0)&&(j!=width-1)){

                                               float t1=kernel[2][2]*imagem[(i-1)*bytesFila+(j-1)*channels];

                                               float t2=kernel[2][1]*imagem[(i-1)*bytesFila+(j)*channels];

                                               float t3=kernel[2][0]*imagem[(i-1)*bytesFila+(j+1)*channels];

                                               float t4=kernel[1][2]*imagem[(i)*bytesFila+(j-1)*channels];

                                               float t5=kernel[1][1]*imagem[(i)*bytesFila+(j)*channels];

                                               float t6=kernel[1][0]*imagem[(i)*bytesFila+(j+1)*channels];

                                               float t7=kernel[0][2]*imagem[(i+1)*bytesFila+(j-1)*channels];

                                               float t8=kernel[0][1]*imagem[(i+1)*bytesFila+(j)*channels];

                                               float t9=kernel[0][0]*imagem[(i+1)*bytesFila+(j+1)*channels];

                                              

                                               int coef=(int)(t1+t2+t3+t4+t5+t6+t7+t8+t9)+clampping*127;

                                               if(coef>255) coef=255;

                                               if(coef<0) coef=0;

 

                                               for(int k=0;k<channels;k++)

                                                           resultado[i*bytesFila+j*channels+k]=coef;

                                              

                                   }else

                                               for(int k=0;k<channels;k++)

                                                           resultado[i*bytesFila+j*channels+k]=imagem[i*bytesFila+j*channels+k];

                        }

            return resultado;

}

 

Primeiro os originais e seus tons de cinza:

 

 


 


 

Resultados do Filtro Gausseano:

 


Resultado do Filtro Laplaciano:

 


Resultado do Passa Altos Genérico:

 


 

Resultados dos outros passa altos:

 

 

Prewitt Horizontal

Prewitt Vertical

Sobel Horizontal

Sobel Vertical

 

 

 

 

 

 

                                                                                                                            19/10/2007 - Lucas Enrique Guaycochea

Hosted by www.Geocities.ws

1