/* * realce.c * * Este programa ilustra as operacoes de processamento * ponto a ponto e filtros espaciais * para destacar detalhes de uma imagem. * Utiliza varias funcoes de processamento de imagens providas * pela OpenGL. * c: Compressao da escala dinamica * n: Negativo * a: Alargamento de Contraste * e: Equalizacao * s: Filro de suavizacao * r: Filtro de agucamento * f: filtro de agucamento 2x * b: filtro de Sobel * x: filtro de Sobel na direcao x * l: filtro laplaciano * d: filtro de desagucamento * * * Importante: GL_EXTENSIONS deve conter GL_ARB_imaging * Utilize a seguinte instrucao para certificar-se: * printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); * * * Ting (27/07/08) */ #define _USE_MATH_DEFINES #ifdef _WIN32 #include #endif #include // Header File For The GLUT Library #include // Header file for standard file i/o. #include // Header file for malloc/free. #include // Header file for math functions. #ifndef _WIN32 extern void glGetMinmax (GLenum, GLboolean, GLenum, GLenum, GLvoid *); extern void glMinmax (GLenum, GLenum, GLboolean); extern void glGetHistogram (GLenum, GLboolean, GLenum, GLenum, GLvoid *); extern void glHistogram (GLenum, GLsizei, GLenum, GLboolean); extern void glConvolutionFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); #endif /* Include here the header of the image to be processed width and height are defined */ #include "child_profile.h" /* ascii code for the escape key */ #define ESCAPE 27 #define HISTOGRAM_SIZE 256 int win; // id da janela principal int swin1, swin2; // id das subjanelas do glut GLubyte pixel[3]; char *data; GLubyte *imagem, *r_imagem, *t_imagem; GLubyte **aux_imagem; GLubyte valores[2]; // valor minimo e maximo dos pixels GLuint values[HISTOGRAM_SIZE]; // distribuicao de frequencias char opt='o'; /***********************************************************/ /* Filtragem Espacial */ GLfloat gaussian[7][7] = { {1.,4.,8.,10.,8.,4.,1.}, {4.,12.,25.,29.,25.,12.,4.}, {8.,25.,49.,58.,49.,25.,8.}, {10.,29.,58.,67.,58.,29.,10.}, {8.,25.,49.,58.,49.,25.,8.}, {4.,12.,25.,29.,25.,12.,4.}, {1.,4.,8.,10.,8.,4.,1.}, }; GLfloat box[3][3] = { {1.,1.,1.}, {1.,1.,1.}, {1.,1.,1.} }; GLfloat aguca[3][3] = { {-1.,-1.,-1.}, {-1.,8.,-1.}, {-1.,-1.,-1.} }; GLfloat sobel_x[3][3] = { {-0.125, 0 , 0.125}, {-0.25, 0 , 0.25}, {-0.125, 0 , 0.125} }; GLfloat sobel_y[3][3] = { {-0.125, -0.25 ,-0.125}, {0 , 0 , 0.}, {0.125 , 0.25 , 0.125} }; GLfloat laplaciano[3][3] = { {-0.125, -0.125, -0.125}, {-0.125, 1.0 , -0.125}, {-0.125, -0.125, -0.125} }; void laplace (void) { glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE, 3, 3, GL_LUMINANCE, GL_FLOAT, laplaciano); glEnable(GL_CONVOLUTION_2D); glRasterPos2i(0, 0); glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, imagem); glDisable(GL_CONVOLUTION_2D); } void sobel (void) { glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE, 3, 3, GL_LUMINANCE, GL_FLOAT, sobel_x); glEnable(GL_CONVOLUTION_2D); glRasterPos2i(0, 0); glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, imagem); glDisable(GL_CONVOLUTION_2D); glReadPixels(0,0,width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, t_imagem); glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE, 3, 3, GL_LUMINANCE, GL_FLOAT, sobel_y); glEnable(GL_CONVOLUTION_2D); glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, t_imagem); glDisable(GL_CONVOLUTION_2D); } void sobelx (void) { glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE, 3, 3, GL_LUMINANCE, GL_FLOAT, sobel_x); glEnable(GL_CONVOLUTION_2D); glRasterPos2i(0, 0); glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, imagem); glDisable(GL_CONVOLUTION_2D); } void reforco1 (void) { glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE, 3, 3, GL_LUMINANCE, GL_FLOAT, aguca); glEnable(GL_CONVOLUTION_2D); glRasterPos2i(0, 0); glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, imagem); glDisable(GL_CONVOLUTION_2D); } void reforco2 (void) { glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE, 3, 3, GL_LUMINANCE, GL_FLOAT, aguca); glEnable(GL_CONVOLUTION_2D); glRasterPos2i(0, 0); glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, imagem); glDisable(GL_CONVOLUTION_2D); glReadPixels(0,0,width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, t_imagem); glEnable(GL_CONVOLUTION_2D); glRasterPos2i(0, 0); glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, t_imagem); glDisable(GL_CONVOLUTION_2D); } void desaguca (void) { int i,j; double aux; glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE, 7, 7, GL_LUMINANCE, GL_FLOAT, gaussian); glEnable(GL_CONVOLUTION_2D); glRasterPos2i(0, 0); glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, imagem); glDisable(GL_CONVOLUTION_2D); glReadPixels(0,0,width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, t_imagem); for (i=(height-1); i >= 0; i--) for (j=(width-1); j >= 0; j--) { aux = (2.0*(float)imagem[i*width+j])-(float)t_imagem[i*width+j]; if (aux < 0) r_imagem[i*width+j]=0; else if (aux > 255) r_imagem[i*width+j] = 255; else r_imagem[i*width+j]=aux; } glRasterPos2i(0,0); glDrawPixels(width,height,GL_LUMINANCE, GL_UNSIGNED_BYTE, r_imagem); } void suave (void) { glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE, 3, 3, GL_LUMINANCE, GL_FLOAT, box); glEnable(GL_CONVOLUTION_2D); glRasterPos2i(0, 0); glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, imagem); glReadPixels(0,0,width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, t_imagem); glDisable(GL_CONVOLUTION_2D); } /***********************************************************/ /* Processamento Ponto a Ponto */ void compressao_escala (void) { int i,j; for (i=(height-1); i >= 0; i--) for (j=(width-1); j >= 0; j--) { r_imagem[i*width+j] = (GLubyte)(45.* log((float)aux_imagem[i][j]+1.)); } } void negativo (void) { int i,j; for (i=(height-1); i >= 0; i--) for (j=(width-1); j >= 0; j--) { r_imagem[i*width+j] = (GLubyte)(255 - aux_imagem[i][j]); } } void alargamento_contraste (void) { int i,j; /* Define o formato da imagem */ glMinmax(GL_MINMAX, GL_LUMINANCE, GL_TRUE); glEnable(GL_MINMAX); glRasterPos2i(0,0); glDrawPixels(width,height,GL_LUMINANCE, GL_UNSIGNED_BYTE, imagem); glGetMinmax(GL_MINMAX, GL_TRUE, GL_LUMINANCE, GL_UNSIGNED_BYTE, valores); glDisable(GL_MINMAX); for (i=(height-1); i >= 0; i--) for (j=(width-1); j >= 0; j--) { r_imagem[i*width+j] = (GLubyte)(255. * ((float)aux_imagem[i][j]-(float)valores[0])/((float)valores[1]-(float)valores[0])); } } void equalizacao (void) { int i,j; int accum[HISTOGRAM_SIZE]; /* Define o formato da imagem da qual será feita a distribuicao de frequencias */ glHistogram(GL_HISTOGRAM, HISTOGRAM_SIZE, GL_LUMINANCE, GL_TRUE); /* Habilita histograma */ glEnable(GL_HISTOGRAM); glRasterPos2i(0, 0); glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, imagem); glGetHistogram(GL_HISTOGRAM, GL_TRUE, GL_LUMINANCE, GL_UNSIGNED_INT, values); glDisable(GL_HISTOGRAM); accum[0] = values[0]; values[0] = (GLubyte)(((float)(accum[0])/((float)(width*height)))*255.); for (i=1; i< HISTOGRAM_SIZE; i++) { accum[i] = values[i] + accum[i-1]; values[i] = (GLubyte)(((float)(accum[i])/(float)(width*height))*255.); } for (i=(height-1); i >= 0; i--) for (j=(width-1); j >= 0; j--) { r_imagem[i*width+j] = values[aux_imagem[i][j]]; } } /***********************************************************/ void init(void) { int i, j; /* definir a cor em preto (0,0,0) como cor de "CLEAR" */ glClearColor (0.0, 0.0, 0.0, 0.0); for (i=0; i<4; i++) for (j=0; j<4; j++) box[i][j] /= 12.; for (i=0; i<4; i++) for (j=0; j<4; j++) aguca[i][j] /= 9.; for (i=0; i<7; i++) for (j=0; j<7; j++) gaussian[i][j] /= 1000.; negativo(); } void main_display(void) { glClearColor(0.8, 0.8, 0.8, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(0.f, 0.f, 0.f); } void display_swin1() { // Desenhar os pixels da image1 glutSetWindow(swin1); // definir a forma como os dados sao desempacotados da memoria glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // definir a forma como os dados sao empacotados na memoria glPixelStorei(GL_PACK_ALIGNMENT, 1); glDisable(GL_DITHER); // resetar as cores nos buffers de cor glClear(GL_COLOR_BUFFER_BIT); //Definir a origem da imagem em coordenadas da janela obtidas //via transformações geométricas e projetivas glRasterPos2i(0,0); glDrawPixels(width,height,GL_LUMINANCE, GL_UNSIGNED_BYTE, imagem); // forcar a execucao dos comandos enviados a OpenGL glFlush(); } void display_swin2() { // Desenhar os pixels da image2 glutSetWindow(swin2); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1); glDisable(GL_DITHER); // resetar as cores nos buffers de cor glClear(GL_COLOR_BUFFER_BIT); if (opt == 's') suave(); else if (opt == 'r') reforco1(); else if (opt == 'b') sobel(); else if (opt == 'x') sobelx(); else if (opt == 'f') reforco2(); else if (opt == 'd') desaguca(); else if (opt == 'l') laplace(); else { glRasterPos2i(0,0); glDrawPixels(width,height,GL_LUMINANCE, GL_UNSIGNED_BYTE, r_imagem); } // forcar a execucao dos comandos enviados a OpenGL glFlush(); } void main_reshape(int w, int h) { glViewport(0,0,(GLsizei)w,(GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, (GLfloat) w, 0.0, (GLfloat) h); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* redefinir a posição e as dimensões da sub-janela 1 */ glutSetWindow(swin1); glutPositionWindow(0, 0); glutReshapeWindow(width, height); /* redefinir a posição e as dimensões da sub-janela 2 */ glutSetWindow(swin2); glutPositionWindow(width,0 ); glutReshapeWindow(width, height); } void reshape_swin1(int w, int h) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, (GLfloat) width, 0.0, (GLfloat) height); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void reshape_swin2(int w, int h) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, (GLfloat) width, 0.0, (GLfloat) height); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } /* ARGSUSED1 */ void keyboard(unsigned char key, int x, int y) { int i; switch (key) { case 'c': // Compressao da escala dinamica opt = 'c'; compressao_escala(); break; case 'n': // Negativo opt = 'n'; negativo(); break; case 'a': // Alargamento de Contraste opt = 'a'; alargamento_contraste(); break; case 'e': // Equalizacao opt = 'e'; equalizacao(); break; case 's': // Filtro suavizacao opt ='s'; break; case 'r': // Filtro de agucamento opt = 'r'; break; case 'f': // Filtro de agucamento 2x opt = 'f'; break; case 'b': // Filtro de Sobel opt = 'b'; break; case 'x': // Filtro de Sobel x opt = 'x'; break; case 'l': // Filtro Laplaciano opt = 'l'; break; case 'd': // Filtro de Desagucamento opt = 'd'; break; case 27: free((char *)imagem); free((char *)r_imagem); free((char *)t_imagem); for (i=0; i= 0; i--) for (j=(width-1); j >= 0; j--) { HEADER_PIXEL(data,pixel) imagem[i*width+j] = pixel[0]; aux_imagem[i][j]=pixel[0]; } glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB ); glutInitWindowSize((int)width*2, (int)height); glutInitWindowPosition(0,0); win = glutCreateWindow(argv[0]); #ifdef _WIN32 // Inicializar glew err = glewInit(); if (GLEW_OK != err) { /* Problem: glewInit failed, something is seriously wrong. */ printf ("glewInit failed.\n"); } if (glewGetExtension("GL_ARB_imaging")) { printf ("GL_ARB_Imaging is supported.\n"); } #endif glutReshapeFunc(main_reshape); glutDisplayFunc(main_display); glutKeyboardFunc(keyboard); swin1 = glutCreateSubWindow(win,(int)width,0,(int)width,(int)height); glutReshapeFunc(reshape_swin1); glutDisplayFunc(display_swin1); glutKeyboardFunc(keyboard); swin2 = glutCreateSubWindow(win,(int)width,0,(int)width,(int)height); glutReshapeFunc(reshape_swin2); glutDisplayFunc(display_swin2); glutKeyboardFunc(keyboard); init(); glutMainLoop(); return(0); }