////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// #include #include #include ////////////////////////////////////////////////////////////// //funcao que realiza a copia do conteudo de imagem para outra void copy_image(image *in, image *out) { int dim_x, dim_y, num_chanell; int i,j,c; //dimensoes da imagem e dos canais de cores dim_x = in->sz[X]; dim_y = in->sz[Y]; num_chanell = in->sz[CHANELL]; //realiza o passeio pela imagem for(i = 0; i < dim_x; i++) { for(j = 0; j < dim_y; j++) { for(c = 0; c < num_chanell; c++) { float *pin = float_image_get_sample_address(in,c,i,j); float *pout = float_image_get_sample_address(out,c,i,j); (*pout) = (*pin); } } } } ////////////////////////////////////////////////////////////////// //funcao responsavel pela reducao da imagem em fator de 2 void reduce_image(image *in, image *out) { int dim_x, dim_y; int i,j,c; //inicia as dimensoes da imagem dim_x = in->sz[X]; dim_y = in->sz[Y]; printf("\n Dimensoes: %d x %d \n",dim_x,dim_y); //realiza o passeio pelos pixels da imagem aplicando uma media for(i = 0; i < dim_x; i = i + 2) { for(j = 0; j < dim_y; j = j + 2) { //para cada canal de cor c = CHANELL; //for(c = R; c < RGB; c++) { //pega os pixels da imagem in float *p1 = float_image_get_sample_address(in,c,i,j); float *p2 = float_image_get_sample_address(in,c,i+1,j); float *p3 = float_image_get_sample_address(in,c,i,j+1); float *p4 = float_image_get_sample_address(in,c,i+1,j+1); //pega o endereço do pixel da imagem out float *p = float_image_get_sample_address(out,c,i/2,j/2); //calcula a media (*p) = ((*p1) + (*p2) + (*p3) + (*p4))/4.0; } } } return; } /////////////////////////////////////////////////////////////////////////////// //funcao que calcula o numero de escala de uma imagem, assumindo potencia de 2 int num_scales_image(int dim_x) { int num_scales = 0; //verifica o numero de escala. OBS: Potencia de 2 if(dim_x == 1) num_scales = 0; if(dim_x == 2) num_scales = 1; if(dim_x == 4) num_scales = 2; if(dim_x == 8) num_scales = 3; if(dim_x == 16) num_scales = 4; if(dim_x == 32) num_scales = 5; if(dim_x == 64) num_scales = 6; if(dim_x == 128) num_scales = 7; if(dim_x == 256) num_scales = 8; if(dim_x == 512) num_scales = 9; if(dim_x == 1024) num_scales = 10; return(num_scales); } /////////////////////////////////////////////////////////////////////////////// //funcao que aloca a estrutura image_mult_escala e produz as diferente escalas //da imagem de entrada, armazenando-as na estrutura. void create_image_mult_scale(image_mult_scale *mult_scale, char * name_image_in) { int dim_x, dim_y, dim_c, i; char name_edges[50]; //realiza a leitura da imagem mult_scale->images[0] = ex_read_image(NULL,name_image_in); //recupera os valores da dimensao da imagem dim_x = mult_scale->images[0]->sz[X]; dim_y = mult_scale->images[0]->sz[Y]; dim_c = mult_scale->images[0]->sz[CHANELL]; //calcula o numero de escalas mult_scale->num_scales = num_scales_image(dim_x); mult_scale->edges[0] = float_image_new(1,mult_scale->images[0]->sz[X],mult_scale->images[0]->sz[Y]); float_image_gradient_sqr_relative_2(mult_scale->images[0],0,0.1,mult_scale->edges[0],0); ex_write_image(NULL,"img/temp_edges0.pgm",mult_scale->edges[0]); printf("\n *** %d Escalas ***",num_scales_image(dim_x)); //cria a piramide de escala for(i = 1; i < mult_scale->num_scales; i++) { //cria uma nova imagem e reduz sua escala mult_scale->images[i] = float_image_new(mult_scale->images[i-1]->sz[CHANELL], (mult_scale->images[i-1]->sz[X])/2,(mult_scale->images[i-1]->sz[Y])/2); reduce_image(mult_scale->images[i-1],mult_scale->images[i]); //recupera os valores da dimensao da imagem dim_x = mult_scale->images[i]->sz[X]; dim_y = mult_scale->images[i]->sz[Y]; dim_c = mult_scale->images[i]->sz[CHANELL]; sprintf(name_edges,"img/temp_edges_scale%d.pgm",i); //mult_scale->edges[i] = float_image_gradient_sqr_relative(mult_scale->images[i],0.08,TRUE); mult_scale->edges[i] = float_image_new(1,mult_scale->images[i]->sz[X],mult_scale->images[i]->sz[Y]); float_image_gradient_sqr_relative_2(mult_scale->images[i],0,0.1,mult_scale->edges[i],0);//0.08 ou 0.1 ex_write_image(NULL,name_edges,mult_scale->edges[i]); } } ///////////////////////////////////////////////////////////////// //funcao que retorna a distacia euclidiana entre dois pixels double distance(int px, int py, int qx, int qy) { //retorna a distancia euclidiana return( sqrt( pow(px-qx,2) + pow(py-qy,2) )); } /////////////////////////////////////////////////////////////////// //funcao que aloca um kernel e preenche os pesos de acordo com a //distancia void create_kernel_circular(kernel *adj, double raio) { int iraio = ceil(raio); int tam = (int)ceil(4*raio*raio); // 2*R x 2*R int x,y; int count = 0; //alocacao das coordenadas e dos pesos adj->adj_x = (int*)malloc(sizeof(int)*tam); adj->adj_y = (int*)malloc(sizeof(int)*tam); adj->w = (double*)malloc(sizeof(double)*tam); //calcula as coordenadas da mascara for(x = -iraio; x <= iraio; x++) { for(y = -iraio; y <= iraio; y++) { if(distance(0,0,x,y) <= raio) { adj->adj_x[count] = x; adj->adj_y[count] = y; count++; } } } //numero de vizinhos adj->n_adj = count-1; } /////////////////////////////////////////////////////////////////// //funcao que aloca e preenche a lista de adjacencia usando o filtro //de sobel void create_kernel_sobel(kernel *adj) { int tam = (int)3*3;//tamanho do filtro adj->adj_x = (int*)malloc(sizeof(int)*tam); adj->adj_y = (int*)malloc(sizeof(int)*tam); adj->w = (double*)malloc(sizeof(double)*tam); adj->n_adj = tam; //atualiza a lista de deslocamento adj->adj_x[0] = -1; adj->adj_y[0] = -1; adj->adj_x[1] = 0; adj->adj_y[1] = -1; adj->adj_x[2] = 1; adj->adj_y[2] = -1; adj->adj_x[3] = -1; adj->adj_y[3] = 0; adj->adj_x[4] = 0; adj->adj_y[4] = 0; adj->adj_x[5] = 1; adj->adj_y[5] = 0; adj->adj_x[6] = -1; adj->adj_y[6] = 1; adj->adj_x[7] = 0; adj->adj_y[7] = 1; adj->adj_x[8] = 1; adj->adj_y[8] = 1; } /////////////////////////////////////////////////////////////////// //funcao que prenche um filtro gaussiano void gaussian_kernel(kernel *adj, double raio) { int i = 0; double sigma = 3.0*raio; double dist; //para todos pontos da adjacencia for(i = 0; i < adj->n_adj; i++) { dist = distance(0,0,adj->adj_x[i],adj->adj_y[i]); adj->w[i] = exp(- (dist*dist) / (2*sigma*sigma) ); } } /////////////////////////////////////////////////////////////////// //funcao que insere os pesos num filtro de sobel x void sobel_x(kernel *adj) { //atribui os pesos de sobel x adj->w[0] = -1.0; adj->w[1] = 0.0; adj->w[2] = 1.0; adj->w[3] = -2.0; adj->w[4] = 0.0; adj->w[5] = 2.0; adj->w[6] = -1.0; adj->w[7] = 0.0; adj->w[8] = 1.0; } /////////////////////////////////////////////////////////////////// //funcao que insere os pesos num filtro de sobel y void sobel_y(kernel *adj) { //atribui os pesos de sobel y adj->w[0] = -1.0; adj->w[1] = -2.0; adj->w[2] = -1.0; adj->w[3] = 0.0; adj->w[4] = 0.0; adj->w[5] = 0.0; adj->w[6] = 1.0; adj->w[7] = 2.0; adj->w[8] = 1.0; } /////////////////////////////////////////////////////////////////// //funcao que realiza a filtragem de um unico pixel int filter_pixel(image *img, int x, int y, kernel *adj) { int i; int ix = 0; int iy = 0; double pixel_val = 0.0; //para todo pixel da relacao de adjacencia for(i = 0; i < adj->n_adj; i++) { ix = x + adj->adj_x[i]; iy = y + adj->adj_y[i]; //evita passar dos limites da imagem if((ix >= 0 && ix < img->sz[X]) && (iy >= 0 && iy < img->sz[Y])) pixel_val += adj->w[i]*float_image_get_sample(img,0,ix,iy); } return((int)pixel_val); } /////////////////////////////////////////////////////////////////// //funcao responsavel pela extracao das arestas usando os filtros de //sobel void extract_edges(image *img, image *img_edges) { int y,x; kernel adj1,adj2; image *i_sobel_x = NULL, *i_sobel_y = NULL; float val1; float val2; //cria as imagens temporarias i_sobel_x = float_image_new(1,img->sz[X],img->sz[Y]); i_sobel_y = float_image_new(1,img->sz[X],img->sz[Y]); //aloca os kernels de sobel create_kernel_sobel(&adj1); create_kernel_sobel(&adj2); //cria os filtros sobel_x(&adj1); sobel_y(&adj2); for(y = 0; y < img->sz[Y]; y++) { for(x = 0; x < img->sz[X]; x++) { //aplica cada um dos filtros val1 = abs(filter_pixel(img,x,y,&adj1)); val2 = abs(filter_pixel(img,x,y,&adj2)); float *px = float_image_get_sample_address(i_sobel_x,0,x,y); float *py = float_image_get_sample_address(i_sobel_y,0,x,y); float_image_set_pixel(i_sobel_x,x,y,&val1); float_image_set_pixel(i_sobel_y,x,y,&val2); (*px) = val1; (*py) = val2; //verifica se esta no limite e joga para a imagem final if( sqrt(pow(val1,2) + pow(val2,2)) >= LIM_MIN) { float val = sqrt( pow(val1,2) + pow(val2,2) ); float (*p) = float_image_get_sample_address(img_edges,0,x,y); (*p) = val; } else { val1 = 0.0; float *p = float_image_get_sample_address(img_edges,0,x,y); (*p) = val1; } } } //desaloca as imagens temporarias float_image_free(i_sobel_x); float_image_free(i_sobel_y); } /////////////////////////////////////////////////////////////////// //funcao que dada duas imagens compara e retorna um valor que indica //a diferenca entre ambas /*float compare_images(image *img1, image *img2, image *masc) { int x,y; float sum = 0.0; float (*p1) = NULL, (*p2) = NULL; int count = 1; //if( img1->sz[X] != img2->sz[X] || img1->sz[Y] != img2->sz[Y]) /*{ printf("\n ERRO - Imagens com dimensoes diferentes - comp_imgs(%d,%d) - CMPI.C",(int)img1->sz[X],(int)img2->sz[X]); exit(1); } for(x = 0; x < masc->sz[X]; x++) { for(y = 0; y < masc->sz[Y]; y++) { if((float_image_get_sample(masc,0,x,y)) == 0.0) { count++; p1 = float_image_get_sample_address(img1,0,x,y); p2 = float_image_get_sample_address(img2,0,x,y); if((*p1) != 0.0 && (*p2) != 0.0) sum += 0.25*fabs((*p1) - (*p2));//0.25 else sum += fabs((*p1) - (*p2)); } } } //printf(" * %f.3 * ",(float)sum/count); return 1.52; //if(count == 1) return((float)INF); //return((float)(sum/count)); }*/ /////////////////////////////////////////////////////////////////// //funcao que realiza o calculo da qualidade (diferenca) entre a img //de entrada e as imgs geradas void calculate_quality(set_of_candidates *candidates, image *img_in, image *img_edge); void calculate_quality(set_of_candidates *candidates, image *img_in, image *img_edge) { int i = 0; image *img_candidate; image *edge; image *masc; char name_img[50]; char name_masc[50]; int dim_x, dim_y, dim_c; for(i = 0; i < candidates->num_candidates; i++) { //le a imagem do candidato i sprintf(name_img,"img/%s%05d.pgm",candidates->candidates[i].model_name,i); img_candidate = ex_read_image(NULL, name_img); //le a mascara do candidato i sprintf(name_masc,"img/masc%05d.pgm",i); masc = ex_read_image(NULL,name_masc); //recupera os valores da dimensao da imagem dim_x = img_candidate->sz[X]; dim_y = img_candidate->sz[Y]; dim_c = img_candidate->sz[CHANELL]; edge = float_image_gradient_sqr_relative(img_candidate,0.4,TRUE); candidates->candidates[i].quality = compare_images(img_edge,edge,masc); // compare_images float_image_free(edge); float_image_free(img_candidate); float_image_free(masc); } return; }