Página principal | Jerarquía de la clase | Lista alfabética | Lista de componentes | Lista de archivos | Miembros de las clases | Archivos de los miembros | Páginas relacionadas

jed_img.C

Ir a la documentación de este archivo.
00001 //===========================================================================
00002 //= jed_img.cc                                                Abril de 1998 =
00003 //=-------------------------------------------------------------------------=
00004 //= Clases de representacion y procesamiento basico de imagenes digitales   =
00005 //=-------------------------------------------------------------------------=
00006 //= ADVERTENCIA: ESTE SOFTWARE NO ESTA CONCEBIDO NI DISENNADO PARA EL USO   =
00007 //= EN EQUIPO DE CONTROL EN LINEA EN ENTORNOS PELIGROSOS QUE REQUIERAN UN   =
00008 //= DESEMPENNO LIBRE DE FALLAS, COMO LA OPERACION DE PLANTAS NUCLEARES,     = 
00009 //= SISTEMAS DE NAVEGACION O COMUNICACION EN AVIONES, TRAFICO AEREO,        =
00010 //= EQUIPO MEDICO DEL CUAL DEPENDAN VIDAS HUMANAS O SISTEMAS DE ARMAMENTO,  =
00011 //= EN LOS CUALES UNA FALLA EN EL SOFTWARE PUEDA IMPLICAR DIRECTAMENTE LA   =
00012 //= MUERTE, DANNOS PERSONALES O DANNOS FISICOS Y/O AMBIENTALES GRAVES       =
00013 //= ("ACTIVIDADES DE ALGO RIESGO").                                         =
00014 //=-------------------------------------------------------------------------=
00015 //= Autor original: Oscar J. Chavarro G.  A.K.A. JEDILINK. Copyright (c),   =
00016 //= 1997 - 2003, oscarchavarro@hotmail.com                                  =
00017 //= AQUYNZA es software libre, y se rige bajo los terminos de la licencia   =
00018 //= LGPL de GNU (http://www.gnu.org). Para mayor informacion respecto a la  =
00019 //= licencia de uso, consulte el archivo ./doc/LICENCIA en la distribucion. =
00020 //===========================================================================
00021 
00022 //= ENCABEZADOS DE LIBRERIAS ================================================
00023 
00024 #include "jed_defs.h"
00025 
00026 //#include <double.h>    // Librerias standard
00027 //#include <limits.h>
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <stdlib.h>
00031 
00032 #ifdef MOTIF_ENABLED        // Librerias X Window System
00033     #include <Xm/Xm.h>
00034 #endif
00035 
00036 #include "jed_gl.h"  // Librerias de OpenGL
00037 
00038 #include "toolkits/media/jed_img.h"
00039 
00040 #undef GL_COMPLETO
00041 
00042 //===========================================================================
00043 //= FUNCIONES                                                               =
00044 //===========================================================================
00045 
00046 #define RANGO(a,b,c) { if (a < b) a = b;  if (a > c) a = c; }
00047 
00048 void
00049 calcular_funcion_gamma(BYTE funcion_gamma[256], double factor)
00050 {
00051     int i, j;
00052     double y, invgam;
00053 
00054     if (factor < 0.0) {
00055       invgam = 1.0 / -factor; /* invgram is now positive */
00056       for (i=0; i<256; i++) {
00057         y = pow( ((double) i / 255.0), invgam) * 255.0;
00058         j = (int) floor(y + 0.5);
00059         RANGO(j,0,255);
00060         funcion_gamma[255-i] = j;    /* store the entries in reverse order */
00061       }
00062     }
00063     else if (factor > 0.0) {
00064       invgam = 1.0 / factor;
00065       for (i=0; i<256; i++) {
00066         y = pow( ((double) i / 255.0), invgam) * 255.0;
00067         j = (int) floor(y + 0.5);
00068         RANGO(j,0,255);
00069         funcion_gamma[i] = j;
00070       }
00071     }
00072     else {  // factor == 0.0 
00073       for (i=0; i<256; i++) funcion_gamma[i] = 0;
00074     }
00075 }
00076 
00077 //===========================================================================
00078 //= CLASE IMAGEN                                                            =
00079 //===========================================================================
00080 
00081 IMAGEN::IMAGEN()
00082 {
00083     //printf("IMAGEN::IMAGEN\t"); fflush(stdout);
00084 }
00085 
00086 IMAGEN::~IMAGEN()
00092 {
00093     //printf("IMAGEN::~IMAGEN\n");  fflush(stdout);
00094 }
00095 
00096 #ifdef NNN
00097 
00098 /* OJO: ESTO NO!
00099 void
00100 IMAGEN::elim(void)
00101 {
00102     fprintf(stderr, "<IMAGEN>-elim: No se debio haber llamado!\n");
00103     // al que se debe llamar es a la version de las clases hijas
00104     fflush(stderr);
00105 }
00106 */
00107 
00108 //= OPERACIONES DE PERSISTENCIA =============================================
00109 
00110 BOOLEAN
00111 IMAGEN::importar_ppm(FILE *fd)
00118 {
00119 #ifdef NONONO
00120     int xtam = 0, ytam = 0;
00121     int i, j;
00122     char buffer[MAX_LINE + 1];
00123     char *ptr = NULL;
00124     PIXEL_RGB pixel;
00125 
00126     if ( !fd ) {
00127         fprintf(stderr, "ERROR: No se puede abrir el archivo.");
00128         fflush(stderr);
00129         return FALSE;
00130     }
00131 
00132     //- Inicializacion basada en los datos de la imagen --------------------
00133     for ( i = 0; !feof(fd); i++ ) {
00134         if ( i >= MAX_LINE ) i = 0;
00135         fread(&buffer[i], sizeof(BYTE), 1, fd);
00136         buffer[i + 1] = '\0';
00137         if ( buffer[i] == '\n' && strcmp(buffer, "255\n") == 0 ) {
00138             break;
00139           }
00140           else if ( buffer[i] == '\n' ) {
00141             ptr = strtok(buffer, " \n");
00142             if ( ptr ) {
00143                 xtam = atoi(ptr);
00144                 ptr = strtok(NULL, " \n");
00145                 if ( ptr ) {
00146                     ytam = atoi(ptr);
00147                 }
00148             }
00149             i = -1;
00150         }          
00151     }
00152 
00153     if ( xtam <= 0 || xtam > 2024 || ytam <=0 || ytam > 2024 ) {
00154         fprintf(stderr, "Imagen con tamanno %d X %d no aceptada.\n",
00155                 xtam, ytam);
00156         fflush(stderr);
00157         return FALSE;
00158     }
00159 
00160     if ( !init(xtam, ytam) ) {
00161         return FALSE;
00162     }
00163     //printf("Creo imagen de %d x %d...\n", x_tam, y_tam);
00164     //fflush(stdout);
00165 
00166     PIXEL_RGB *fila;
00167 
00168     for ( i = y_tam - 1; i >= 0 ; i-- ) {
00169         fila = &((PIXEL_RGB *)Data)[i*x_tam];
00170         for ( j = 0; j < x_tam ; j++ ) {
00171             fread(&pixel, sizeof(PIXEL_RGB), 1, fd);
00172             //if ( pixel[0] < 5 && pixel[1] < 5 && pixel[2] < 5 ) {
00173               //pixel[0] = 73; pixel[1] = 97; pixel[3] = 117;
00174               //pixel[0] = (i*256)/Y_image; pixel[1] = pixel[2] = 0;
00175             //}
00176             fila[j] = pixel;
00177         }
00178     }
00179 
00180 #endif
00181     return TRUE;
00182 }
00183 
00184 //===========================================================================
00185 //= Clase IM_HISTOGRAMA                                                     =
00186 //===========================================================================
00187 
00188 IM_HISTOGRAMA::IM_HISTOGRAMA()
00189 {
00190     int i;
00191 
00192     for ( i = 0; i < 256; i++ ) {
00193         data[i] = 0;
00194     }
00195 }
00196 
00197 void
00198 IM_HISTOGRAMA::calcule(IMAGEN_PAL &imagen_grises)
00199 {
00200     int x, y;
00201     BYTE index;
00202 
00203     for ( x = 0; x < imagen_grises.xtam(); x++ ) {
00204         for ( y = 0; y < imagen_grises.ytam(); y++ ) {
00205             index = imagen_grises.getcolorindex(x, y);
00206             data[index % 256]++;
00207         }
00208     }
00209 }
00210 
00211 #ifdef GL_ENABLED
00212 void
00213 IM_HISTOGRAMA::pintar_gl(BYTE umbral)
00218 {
00219     //- Configuracion de OpenGL ----------------------------------------------
00220     glMatrixMode(GL_PROJECTION);    glPushMatrix();
00221     glLoadIdentity();
00222     glMatrixMode(GL_MODELVIEW);     glPushMatrix();
00223     glLoadIdentity();
00224     // OJO: Falta manejar otras cosas como desactivar el modelo de iluminacion
00225     // y el depth-test para forzar la cosa a salir siempre en 2D
00226 
00227     //- Algoritmo de visualizacion del histograma ----------------------------
00228     int i;
00229     long max = 0;
00230     double x1 = -0.9, x2 = 0.9, y1 = -0.8, y2 = 0.8;
00231 
00232     for ( i = 0; i < 256; i++ ) {
00233         if ( data[i] > max ) max = data[i]; 
00234     }
00235 
00236     //glLineWidth(2.5);
00237     glColor3f(1, 0, 0);
00238     glBegin(GL_LINES);
00239     for ( i = 0; i < 256; i++ ) {
00240         glVertex2d(x1 + (double)i/256, y1);
00241         glVertex2d(x1 + (double)i/256, y1 + ((double)data[i])/((double)max));
00242     }
00243     glEnd();
00244 
00245     glColor3f(1, 1, 0);
00246     glBegin(GL_LINES);
00247         glVertex2d(x1, y1);    glVertex2d(x1, y2);
00248         glVertex2d(x1, y1);    glVertex2d(x2, y1);
00249     glEnd();
00250 
00251     if ( umbral > 0 && umbral < 255 ) {
00252         glColor3f(0, 1, 0);
00253         glBegin(GL_LINES);
00254             glVertex2d(x1 + (double)umbral/256, y1);
00255             glVertex2d(x1 + (double)umbral/256, y2);
00256         glEnd();
00257     }
00258 
00259     //- Salida ---------------------------------------------------------------
00260     glMatrixMode(GL_MODELVIEW);    glPopMatrix();
00261     glMatrixMode(GL_PROJECTION);   glPopMatrix();
00262     glMatrixMode(GL_MODELVIEW);
00263 }
00264 #endif
00265 
00266 void
00267 IM_HISTOGRAMA::imprima(void)
00268 {
00269     int i;
00270 
00271     for ( i = 0; i < 256; i++ ) {
00272       //printf("H[%d] = %d.\n", i, data[i]);
00273         // Esta version simplificada facilita la integracion con aplicaciones
00274         // externas como "Khoros".
00275         printf("%ld\n", data[i]);
00276     }
00277     fflush(stdout);
00278 }
00279 
00280 BYTE
00281 IM_HISTOGRAMA::generar_umbral_seleccion_iterativa(void)
00282 /*
00283 Tomado del cookbook [????], capitulo 3, ejemplo thris
00284 */
00285 {
00286     long i, told, umbral, a, b, c, d, N;
00287 
00288     //- Calcule el valor promedio de intensidad de gris en la imagen -------
00289     umbral = 0;  N = 0;
00290     for ( i = 0; i < 256; i++ ) {
00291         umbral += i * data[i];
00292         N += data[i];
00293     }
00294     umbral = (long)(umbral/(double)N);
00295 
00296     // NPI de porque este ciclo! 
00297     do {
00298         told = umbral;
00299         a = 0; b = 0;
00300         for ( i=0; i <= told; i++ ) {
00301             a += i*data[i];
00302             b += data[i];
00303         }
00304         b += b;
00305 
00306         c = 0; d = 0;
00307         for ( i = told + 1; i < 256; i++ ) {
00308             c += i*data[i];
00309             d += data[i];
00310         }
00311         d += d;
00312 
00313         if ( b == 0 ) b = 1;
00314         if ( d == 0 ) d = 1;
00315         umbral = a/b + c/d;
00316     } while ( umbral != told );
00317 
00318     return (BYTE)umbral;
00319 }
00320 
00321 BYTE
00322 IM_HISTOGRAMA::generar_umbral_otsu(void)
00330 {
00331     int min_index, max_index, i, umbral;
00332     double p[260], y, z, media_global, varianza_global;
00333     long N;
00334 
00335     for ( i = 0, N = 0; i < 256; i++ ) N += data[i]; // Puntos en la imagen
00336 
00337     //- Normalice el histograma en una funcion de distribucion 'p' -----------
00338     for ( i = 0; i < 260; i++ ) p[i] = 0.0;
00339     for ( i = 1; i <= 256; i++ ) {    
00340         p[i] = (double)data[i-1]/(double)N;
00341     }
00342 
00343     //- Minimize la varianza entre grupos ------------------------------------
00344     // Calcule media y varianza globales
00345     media_global = otsu_u(p, 256);
00346     varianza_global = 0.0;
00347     for ( i = 1; i <= 256; i++ ) {
00348         varianza_global += (i-media_global) * (i-media_global) * p[i];
00349     }
00350 
00351     // Notese que solo se considera el maximo intervalo del histograma que ni
00352     // empieza ni termina con un valor de 0. Aqui se calcula dicho intervalo:
00353     for ( i = 1, min_index = -1, max_index = -1; i <= 256; i++ ) {
00354         if ( (min_index < 0) && (p[i] > 0.0) ) min_index = i;
00355         if ( p[i] > 0.0 ) max_index = i;                  
00356     }
00357 
00358     // Seleccione el umbral
00359     z = -1.0;  umbral = 0;
00360     for ( i = min_index; i <= max_index; i++ ) {
00361         y = otsu_nu(p, i, media_global, varianza_global);  //- Calcule NU -
00362         if ( y >= z ) {                  // Es el mayor?
00363             z = y;                       // Si! ==> Guarde el valor y el indice
00364             umbral = i;
00365         }
00366     }
00367 
00368     return (BYTE)umbral;
00369 }
00370 
00371 double
00372 IM_HISTOGRAMA::otsu_u(double *p, int k)
00377 {
00378     int i;
00379     double x = 0.0;
00380 
00381     for ( i = 1; i <= k; i++ ) x += (double)i * p[i];
00382     return x;
00383 }
00384 
00385 double
00386 IM_HISTOGRAMA::otsu_w(double *p, int k)
00391 {
00392     int i;
00393     double x=0.0;
00394 
00395     for ( i = 1; i <= k; i++ ) x += p[i];
00396     return x;
00397 }
00398 
00399 double
00400 IM_HISTOGRAMA::otsu_nu(double *p,int k,double media_global,double varianza_global)
00401 /*
00402 OJO: ???  -Esto no se entiende!-
00403 */
00404 {
00405     double x, sum;
00406 
00407     sum = otsu_w(p, k);
00408     x = media_global * sum - otsu_u(p, k);
00409     x = x * x;
00410     sum = sum * (1.0 - sum);
00411     if ( sum > 0 ) {
00412         x = x/sum;
00413       }
00414       else {
00415         x = 0.0;
00416     }
00417     return x / varianza_global;
00418 }
00419 
00420 /* OJO: ESTO NO!
00421 BOOLEAN
00422 IMAGEN::init(int width, int height)
00423 {
00424     printf("Imagen en %d x %d? No debio pasar!\n", width, height);
00425     fflush(stdout);
00426     return FALSE;
00427 }*/
00428 
00429 #endif // NNN
00430 
00431 //===========================================================================
00432 //= EOF                                                                     =
00433 //===========================================================================
00434 

Este archivo HTML ha sido generado automáticamente a partir del código fuente AQUYNZA. NO LO EDITE. Para mayor información contacte al autor.