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