#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include //#define NOISE 0.0500 #define NOISE 0.1000 #define YBIAS 0.0001 #define MAXVALUE 1 //INTERNAS void calculaSQRT_Canal(float_image_t *img,int ch,float *max); float_image_t *calculaGradiente(float_image_t *yuv); float_image_t *calculaGradienteNormal(float_image_t *yuv); void ajustaCanaisGravacao(float_image_t *img); float_image_t *ajustaGradiente(float_image_t *grad,float_image_t *yuv,float max); float_image_t *criaImagemRGB(float_image_t *img); void testaCanais(float_image_t *img); //IMPLEMENTAÇÕES float_image_t *criaImagemYUV(float_image_t *img) { int i,j,ch; frgb_t rgb = (frgb_t){{0,0,0}}; float_image_t *yuv=float_image_new(img->sz[0],img->sz[1],img->sz[2]); //for (ch=0;chsz[0];ch++) { vmin->c[ch] = +INF; vmax->c[ch] = -INF; } for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { if (img->sz[0] == 1) { rgb.c[0] = float_image_get_sample(img,0,i,j); } else if (img->sz[0] == 3) { for (ch=0;chsz[0];ch++) { rgb.c[ch]=float_image_get_sample(img,ch,i,j); } frgb_to_YUV(&rgb); frgb_YUV_to_Yuv(&rgb,YBIAS); } else { assert(FALSE); } for (ch=0;chsz[0];ch++) { float val = rgb.c[ch]; if(isnan(val)){ val = (ch==0?0.5:0.0); } if ((ch==0)&&(val>1.0)){printf("Val=%8.6f\n",val);} float_image_set_sample(yuv,ch,i,j,val); } } } return yuv; } void calculaSQRT_Canal(float_image_t *img,int ch,float *max) { int i,j; float valor=0.0; for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { valor=float_image_get_sample(img,ch,i,j); //valor = sqrt(valor); float_image_set_sample(img,ch,i,j,valor); if (*maxsz[0],yuv->sz[1],yuv->sz[2]); //printf("Image\n"); for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { for (ch=0;chsz[0];ch++) { if (ch==0) { valorGrad=float_image_get_sample(grad,ch,i,j); if (yuv->sz[0]>1) { valor=(valorGrad/max); valor=0.5*(valor+1); //valor=((valorGrad/max)/2)+0.5; //valor= 0.5 - valor/2; } else { valor=(valorGrad/max); /*if (valor>0) { printf("Pixel->Max: %f, Valor: %f, Grad: %f\n",max,valor,valorGrad); }*/ } } else { valor=float_image_get_sample(yuv,ch,i,j); } float_image_set_sample(img,ch,i,j,valor); } } } return img; } float_image_t *calculaGradiente(float_image_t *yuv) { float_image_t *grad=float_image_new(1,yuv->sz[1],yuv->sz[2]); float_image_gradient_sqr_relative_2(yuv,0,NOISE,grad,0); float max=-INF; calculaSQRT_Canal(grad,0,&max); float_image_t *adj=ajustaGradiente(grad,yuv,max); float_image_free(grad); ajustaCanaisGravacao(adj); return adj; } float_image_t *calculaGradienteNormal(float_image_t *yuv) { float_image_t *grad=float_image_new(1,yuv->sz[1],yuv->sz[2]); float_image_gradient_sqr_sobel(yuv, 0, grad, 0); float max=-INF; calculaSQRT_Canal(grad,0,&max); /* if (MAXVALUE>max) max=MAXVALUE;*/ float_image_t *adj=ajustaGradiente(grad,yuv,max); float_image_free(grad); ajustaCanaisGravacao(adj); return adj; } void ajustaCanaisGravacao(float_image_t *img) { int i,j,ch; float valor; for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { for (ch=0;chsz[0];ch++) { valor=float_image_get_sample(img,ch,i,j); if (ch==0) { if (valor>1) { valor=1; } else if (valor<0) { valor=0; } } else { if (valor>+1) { valor=+1; } else if (valor<-1) { valor=-1; } } float_image_set_sample(img,ch,i,j,valor); } } } } float_image_t *criaImagemRGB(float_image_t *img) { int i,j,ch; frgb_t rgb; float_image_t *res=float_image_new(img->sz[0],img->sz[1],img->sz[2]); for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { for (ch=0;chsz[0];ch++) { rgb.c[ch]=float_image_get_sample(img,ch,i,j); } frgb_YUV_from_Yuv(&rgb,YBIAS); frgb_from_YUV(&rgb); frgb_clip_rgb(&rgb); for (ch=0;chsz[0];ch++) { if(isnan(rgb.c[ch])){ rgb.c[ch] = (ch==0?0.5:0.0); } float_image_set_sample(res,ch,i,j,rgb.c[ch]); } } } return res; } void testaCanais(float_image_t *img) { int i,j,ch; for (ch=0;chsz[0];ch++) { float max = -INFINITY, min = +INFINITY; for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { float valor=float_image_get_sample(img,ch,i,j); if (isnan(valor)) { //fprintf(stderr,"X:%d, Y:%d, CH:%d\n",i,j,ch); float_image_set_sample(img,ch,i,j,0.5); } if (valor > max) { max = valor; } if (valor < min) { min = valor; } } } //fprintf(stderr,"channel %d range [ %9.6f _ %9.6f ]\n",ch,min,max); } } void criaImagemYUV_Gradiente(char *bandir,char *nome,char *outdir) { char *filename = jsprintf("%s/%s/norm.ppm",bandir,nome); float_image_t *img=getImageOpenRGB(filename,2); frgb_t tt = (frgb_t){{ 0.5, 0.3, 0.4 }}; frgb_YUV_to_Yuv(&tt, 0.01); frgb_YUV_from_Yuv(&tt, 0.01); frgb_print(stderr, "test = ", &tt, "\n"); fprintf(stderr, "Criando imagem gradiente RGB\n"); float_image_t *gradRGB = criaImagem_Gradiente(img); fprintf(stderr, "Testando imagem gradiente RGB\n"); testaCanais(gradRGB); fprintf(stderr, "Gravando imagem gradiente RGB\n"); char *filename = jsprintf("%s/%s/norm.ppm",outdir,nome); ex_write_image(NULL,filename,gradRGB,2); float_image_free(gradRGB); float_image_free(img); free(filename); } float_image_t *criaImagem_Gradiente(float_image_t *img) { if (img!=NULL) { float_image_t *yuv=criaImagemYUV(img); float_image_t *grad=calculaGradiente(yuv); float_image_free(yuv); float_image_t *rgb=criaImagemRGB(grad); float_image_free(grad); //testaCanais(rgb); return rgb; } else { assert(FALSE); return img; } } float_image_t *criaImagem_Gradiente_Normal(float_image_t *img) { if (img!=NULL) { float_image_t *yuv=criaImagemYUV(img); float_image_t *grad=calculaGradienteNormal(yuv); float_image_free(yuv); float_image_t *rgb=criaImagemRGB(grad); float_image_free(grad); //testaCanais(rgb); return rgb; } else { assert(FALSE); return img; } } //operacoes para separação dos canais entre RGB,YUV e Yuv. Grava todos os resultados em arquivos em um destino informado. //prototipos void gravaCadaCanal(float_image_t *img,char *dir,char *nome); float_image_t *criaRGB_para_YUV(float_image_t *img); float_image_t *criaYUV_para_Yuv(float_image_t *img); float_image_t *criaYuv_para_YUV(float_image_t *img); float_image_t *criaYUV_para_RGB(float_image_t *img); //implementacoes void gravaCadaCanal(float_image_t *img,char *dir,char *nome) { int i,j,c; float_image_t *novo=float_image_new(img->sz[0],img->sz[1],img->sz[2]); char *filename = jsprintf("%s/%s",dir,nome); for (c=0;csz[0];c++) { for (i=0;isz[1];i++) for (j=0;jsz[2];j++) { float_image_set_sample(novo,c,i,j,float_image_get_sample(img,c,i,j)); if (c==0) { float_image_set_sample(novo,1,i,j,0); float_image_set_sample(novo,2,i,j,0); } else if (c==1) { float_image_set_sample(novo,0,i,j,0); float_image_set_sample(novo,2,i,j,0); } else { float_image_set_sample(novo,0,i,j,0); float_image_set_sample(novo,1,i,j,0); } } char *n = jsprintf("%s%d.ppm",filename,c); ex_write_image(NULL,n,novo,2); } } float_image_t *criaRGB_para_YUV(float_image_t *img) { int i,j,ch; frgb_t rgb = (frgb_t){{0,0,0}}; float_image_t *novo=float_image_new(img->sz[0],img->sz[1],img->sz[2]); for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { if (img->sz[0] == 1) { rgb.c[0] = float_image_get_sample(img,0,i,j); } else if (img->sz[0] == 3) { for (ch=0;chsz[0];ch++) { rgb.c[ch]=float_image_get_sample(img,ch,i,j); } frgb_to_YUV(&rgb); } else { assert(FALSE); } for (ch=0;chsz[0];ch++) { float val = rgb.c[ch]; if(isnan(val)){ val = (ch==0?0.5:0.0); } float_image_set_sample(novo,ch,i,j,val); } } } return novo; } float_image_t *criaYUV_para_Yuv(float_image_t *img) { int i,j,ch; frgb_t YUV = (frgb_t){{0,0,0}}; float_image_t *novo=float_image_new(img->sz[0],img->sz[1],img->sz[2]); for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { if (img->sz[0] == 1) { YUV.c[0] = float_image_get_sample(img,0,i,j); } else if (img->sz[0] == 3) { for (ch=0;chsz[0];ch++) { YUV.c[ch]=float_image_get_sample(img,ch,i,j); } frgb_YUV_to_Yuv(&YUV,YBIAS); } else { assert(FALSE); } for (ch=0;chsz[0];ch++) { float val = YUV.c[ch]; if(isnan(val)){ val = (ch==0?0.5:0.0); } float_image_set_sample(novo,ch,i,j,val); } } } return novo; } float_image_t *criaYuv_para_YUV(float_image_t *img) { int i,j,ch; frgb_t Yuv; float_image_t *novo=float_image_new(img->sz[0],img->sz[1],img->sz[2]); for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { for (ch=0;chsz[0];ch++) { Yuv.c[ch]=float_image_get_sample(img,ch,i,j); } frgb_YUV_from_Yuv(&Yuv,YBIAS); for (ch=0;chsz[0];ch++) { if(isnan(Yuv.c[ch])){ Yuv.c[ch] = (ch==0?0.5:0.0); } float_image_set_sample(novo,ch,i,j,Yuv.c[ch]); } } } return novo; } float_image_t *criaYUV_para_RGB(float_image_t *img) { int i,j,ch; frgb_t rgb; float_image_t *novo=float_image_new(img->sz[0],img->sz[1],img->sz[2]); for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { for (ch=0;chsz[0];ch++) { rgb.c[ch]=float_image_get_sample(img,ch,i,j); } frgb_from_YUV(&rgb); frgb_clip_rgb(&rgb); for (ch=0;chsz[0];ch++) { if(isnan(rgb.c[ch])){ rgb.c[ch] = (ch==0?0.5:0.0); } float_image_set_sample(novo,ch,i,j,rgb.c[ch]); } } } return novo; } void separa_canais(float_image_t *img,char *dest) { if (img!=NULL) { gravaCadaCanal(img,dest,"RGB"); float_image_t *YUV=criaRGB_para_YUV(img); gravaCadaCanal(YUV,dest,"YUV"); float_image_t *Yuv=criaYUV_para_Yuv(YUV); gravaCadaCanal(Yuv,dest,"Yuv"); YUV=criaYuv_para_YUV(Yuv); gravaCadaCanal(YUV,dest,"YUV_"); img=criaYUV_para_RGB(YUV); gravaCadaCanal(img,dest,"RGB_"); float_image_free(YUV); float_image_free(Yuv); } else { assert(FALSE);} } //calcula gradiente em cada canal da imagem //PROTOTIPO float_image_t *ajustaCanal(float_image_t *grad,int canal,float max); float_image_t *calculaGradiente(float_image_t *img); float_image_t *criaImagem_Gradiente_por_Canal(float_image_t *img); //IMPLEMENTACOES float_image_t *ajustaCanal(float_image_t *grad,int canal,float max) { int i,j; float valorGrad=0; float valor=0; for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { valorGrad=float_image_get_sample(grad,canal,i,j); valor=(valorGrad/max); //valor=((valorGrad/max)/2)+0.5; valor= 1 - valor/2; float_image_set_sample(grad,canal,i,j,valor); } } return grad; } float_image_t *calculaGradiente_Canais(float_image_t *img) { float_image_t *grad=float_image_new(img->sz[0],img->sz[1],img->sz[2]); int i; float max; for (i=0;isz[0];i++) { float_image_gradient_sqr_relative_2(img,i,NOISE,grad,i); calculaSQRT_Canal(grad,i,&max); grad=ajustaCanal(grad,i,max); } ajustaCanaisGravacao(grad); return grad; } float_image_t *criaImagem_Gradiente_por_Canal(float_image_t *img) { if (img!=NULL) { float_image_t *grad=calculaGradiente_Canais(img); return grad; } else { assert(FALSE); return img; } } //calcula o gradiente normalizado com valor máximo comum para três A,B,C void calculaGradienteABC(float_image_t **A,float_image_t **B,float_image_t **C) { float_image_t *Ayuv=criaImagemYUV(*A); float_image_t *Byuv=criaImagemYUV(*B); float_image_t *Cyuv=criaImagemYUV(*C); float_image_t *Agrad=float_image_new(1,Ayuv->sz[1],Ayuv->sz[2]); float_image_t *Bgrad=float_image_new(1,Byuv->sz[1],Byuv->sz[2]); float_image_t *Cgrad=float_image_new(1,Cyuv->sz[1],Cyuv->sz[2]); float_image_gradient_sqr_sobel(Ayuv, 0, Agrad, 0); float_image_gradient_sqr_sobel(Byuv, 0, Bgrad, 0); float_image_gradient_sqr_sobel(Cyuv, 0, Cgrad, 0); float max=-INF; float max1=-INF; float max2=-INF; float max3=-INF; calculaSQRT_Canal(Agrad,0,&max1);printf("Max1: %f\n",max1); calculaSQRT_Canal(Bgrad,0,&max2);printf("Max2: %f\n",max2); calculaSQRT_Canal(Cgrad,0,&max3);printf("Max3: %f\n",max3); max=max1; if (maxnome=nome; novo->grad=img; novo->prox=NULL; return novo; } void inserePilha(Gradiente **gradiente,char *nome,float_image_t *img) { Gradiente *novo=criaNoGrad(nome,img); if (*gradiente==NULL) *gradiente=novo; else { novo->prox=*gradiente; *gradiente=novo; } } Gradiente *removePilha(Gradiente **gradiente) { if (*gradiente!=NULL) { Gradiente *primeiro=*gradiente; *gradiente=primeiro->prox; return primeiro; } return NULL; } void inicializaHistograma(int h[],int nh) { int i; for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { for (ch=0;chsz[0];ch++) { if (ch==0) { valor=float_image_get_sample(grad,ch,i,j); //if (valor>1){valor=1.0;} } else { valor=float_image_get_sample(yuv,ch,i,j); } float_image_set_sample(grad,ch,i,j,valor); } } } } float_image_t *calculaGradienteHistograma(float_image_t *img) { if (img!=NULL) { float_image_t *yuv=criaImagemYUV(img); float_image_t *grad=float_image_new(yuv->sz[0],yuv->sz[1],yuv->sz[2]); float_image_gradient_sqr_relative_2(yuv,0,NOISE,grad,0); adicionaGradienteHistograma(grad,yuv); float_image_free(yuv); return grad; } else { assert(FALSE); return img; } } float_image_t *normalizaImagemHistograma(float_image_t *img,float max,int canais) { int i,j; float valor; for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { valor=float_image_get_sample(img,0,i,j); valor=(valor/max); if (canais>1) { valor=0.5*(valor+1); } float_image_set_sample(img,0,i,j,valor); } } return img; } void montaHistogramaCanal(float_image_t *img,int h[],int nh) { int i,j,iv; float valor; for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { valor=float_image_get_sample(img,0,i,j); iv=(int)floor(valor*nh); //if (iv<0) { iv=iv*(-1); } if (iv==nh){iv=nh-1;} //if (iv > (int)(nh*0.99)) { printf("Valor= %8.6f,IV=%d\n",valor,iv); } h[iv]++; } } } void obtemMaiores(int h[],float *max,int nh) { int n=nh-1; *max=0; while (n>=0) { if (h[n]>0) { *max=(float)((n+0.5)/nh); break;} else { n--; } } fprintf(stderr,"O max global é: %8.6f na pos %d do histograma\n",*max,n); } float_image_t *geraHistograma(float_image_t *img,int h[],int nh) { float_image_t *grad=calculaGradienteHistograma(img); montaHistogramaCanal(grad,h,nh); return grad; } void gravaHistograma(char *dest,int h[],int nh) { float valor=0; int n=0; FILE *arq; char *nomeArq = jsprintf("%s/histograma.txt",dest); arq = fopen(nomeArq, "w"); while (n0) { valor=(float)((n+0.5)/nh); fprintf(arq,"%d %8.6f %d\n",n,valor,h[n]); fflush(arq); } } n++; } fclose(arq); } void limpaPilha(Gradiente **gradiente) { Gradiente *aux=NULL; Gradiente *grad=*gradiente; while (grad!=NULL) { aux=grad; grad=grad->prox; float_image_t *img=aux->grad; //char *nome=aux->nome; float_image_free(img); //free(nome); free(aux); } } void gravaImagemGradDisco(float_image_t *img,char *nome) { FILE *arq; char *nomeArq = jsprintf("Temp/%s.cim",nome); arq = fopen(nomeArq, "wb"); int i,j; for (i=0;isz[1];i++) { for (j=0;jsz[2];j++) { float Y=float_image_get_sample(img,0,i,j); float u=float_image_get_sample(img,1,i,j); float v=float_image_get_sample(img,2,i,j); fprintf(arq,"%f %f %f\n",Y,u,v); } } fclose(arq); } float_image_t *leImagemGradDisco(char *nome,int c,int w,int h) { FILE *arq; char *nomeArq = jsprintf("Temp/%s.cim",nome); arq = fopen(nomeArq, "rb"); int i,j; float Y,u,v; float_image_t *img=float_image_new(c,w,h); for (i=0;isz[0]==1) { float_image_t *nova=float_image_new(3,img->sz[1],img->sz[2]); int i,j,c; for (i=0;isz[1];i++) for (j=0;jsz[2];j++) { float valor=float_image_get_sample(img,0,i,j); for (c=0;csz[0];c++) { float_image_set_sample(nova,c,i,j,valor); } } float_image_free(img); return nova; } else { return img; } } void rodaHistogramaBase(char *bandir,char *dest,char *nome_imagem[],int numImgs,int canais,int nh,int op,int mem) { int i; if (canais==1) char *nome = jsprintf("Md/R00.pgm"); else if (canais==3) char *nome = jsprintf("Md/R00.ppm"); else { fprintf(stderr,"Canal só pode ser 1 ou 3"); assert(FALSE); } int h[nh+faixa]; int width,height; Gradiente *gradiente=NULL; inicializaHistograma(h,nh+faixa); fprintf(stderr,"Calculando Gradiente...\n"); for (i=0;isz[1]; height=img->sz[2]; } else { inserePilha(&gradiente,nome_imagem[i],grad); //insere a imagem com gradiente na pilha } float_image_free(img); } if (op==0) { fprintf(stderr,"Gravando Histograma...\n"); gravaHistograma(dest,h,nh); if (mem==1) { fprintf(stderr,"Limpando Pilha...\n"); limpaPilha(&gradiente); } } else { float max=0; obtemMaiores(h,&max,nh); fprintf(stderr,"Normalizando Imagens...\n"); if (mem==0) { for (i=0;i%d\n",rgb->sz[0]); char *filename = jsprintf("%s/%s/norm.ppm",dest,nome_imagem[i]); fprintf(stderr,"Imagem gradiente %s para %s\n",nome_imagem[i],filename); ex_write_image(NULL,filename,rgb,2); float_image_free(img); float_image_free(rgb); } } else { Gradiente *aux=removePilha(&gradiente); while (aux!=NULL) { char *filename = jsprintf("%s/%s/norm.ppm",dest,aux->nome); fprintf(stderr,"Imagem gradiente %s para %s\n",aux->nome,filename); aux->grad=normalizaImagemHistograma(aux->grad,max,canais); float_image_t *rgb=criaImagemRGB(aux->grad); rgb=getImagemPPM(rgb); //printf("Canais->%d\n",rgb->sz[0]); ex_write_image(NULL,filename,rgb,2); float_image_free(aux->grad); free(aux); float_image_free(rgb); aux=removePilha(&gradiente); } } } }