lunes, 18 de octubre de 2010

Binarización de imágenes

La primera fase de mi proyecto, es binarizar las imágenes para facilitar el procesamiento posterior. Esto lo tengo implementado desde hace bastante, pero en su momento cuando busqué me costó encontrar la mejor opción.

Binarizar una imagen es cambiar todos sus colores en sólo dos, dependiendo de un umbral dado. Por ejemplo si tenemos una imagen en escala de grises y queremos que sea blanco y negro, lo que hacemos es escoger un valor de gris que será el umbral. Dentro de la imagen todos los valores menores que el umbral serán negro y los mayores blanco.


Como se puede observar el algoritmo es bastante sencillo, el problema aquí sería escoger el valor del umbral, de tal manera que la imagen no sea totalmente blanco o totalmente negra, sino que se distingan las formas.
La mejor opción sería que este umbral se escogiera según los valores de la imagen, de tal manera que el valor elegido no dependa del usuario sino de la propia imagen. Esto es lo que os voy a explicar.


El algoritmo para la selección del umbral lo que hace es iterativamente calcular un nuevo umbral, de tal manera que el bucle acabe cuando el nuevo umbral sea igual al calculado en la iteración anterior.


El valor inicial escogido como umbral será la media de todos los valores de la imagen.

A partir de aquí calculamos los nuevos valores del umbral, calculando la media de los valores de la imagen que están por encima y por debajo del umbral anterior.

Bueno creo que así es un poquito difícil entenderlo así que dejo el código que es más sencillo. En este caso se trabaja con imágenes en escala de grises:


//se calcula el valor inicial del umbral
double umbral0 = 0;

for (int i = 0; i < filas; i++){

    for (int j = 0; j < columnas; j++){
        umbral0 += imagen[i][j];
    }
}

umbral0 = umbral0 / (filas*columnas);

//vamos a calcular el valor real

double umbral1 = 0;
double umbral_der = 0;
double umbral_izq = 0;
int cont_izq = 0;
int cont_der = 0;

while( abs(umbral0 - umbral1) > 0){
    umbral1 = umbral0;
    umbral_der = 0;
    umbral_izq = 0;
    cont_izq = 0;
    cont_der = 0;

    for (int i = 0; i < filas; i ++){

        for (int j = 0; j < columnas; j++){ 

            if (imagen[i][j] < umbral1){
                umbral_izq += imagen[i][j];
                cont_izq ++;
            }

            else{
                umbral_fer += imagen[i][j];
                cont_der ++;
            }
        
    }

    umbral0 = (umbral_izq/cont_izq + umbral_der/cont_der)/2;
}


A continuación os muestro unos ejemplillos del resultado :D



No hay comentarios:

Publicar un comentario