El filtro de mediana nos causó más complicaciones, debido fundamentalmente al uso de punteros en C.
El objetivo del filtro de mediana es eliminar ruido y suavizar la imagen; sus efectos pueden comprobarse en anteriores entradas. Debido a que este filtro tiene en cuenta el valor de los vecinos de cada píxel para determinar si éste deberá ser blanco o negro, para implementarlo fue necesario crear primero una subrutina "getUnos". Dado un array bidimensional de imagen y unas coordenadas de posición inicial y final, coge el parche correspondiente de dicha imagen y cuenta el número de bits 1 en el mismo. Este método incluye un paso por referencia de la variable en la que guardaremos el número de unos, y fue esto lo que nos causó una serie de problemas iniciales debido a nuestra falta de familiaridad con punteros.
Una vez creada esta subrutina, el método de filtro de mediana se simplifica: recorremos la imagen a procesar píxel a píxel, y para cada uno cogemos un parche de la imagen alrededor de ese píxel (el radio del parche se especifica en la llamada al método); el método getUnos nos devuelve el número de unos en ese parche y según superen o no un umbral reescribimos el píxel central como 0 o 1. De esta forma determinamos si un píxel debe ser blanco o negro según sus vecinos.
Por supuesto, tenemos en cuenta que no debemos salirnos de la imagen en ningún momento (si cogemos la coordenada (0,0) con radio 2, el parche irá de (0,0) a (2,2), sin coger coordenadas negativas). Además, en todo este proceso tenemos que tener en cuenta la agrupación por bytes de los bits de imagen, con lo cual realizamos varias multiplicaciones y divisiones por ocho a lo largo del código; para una mayor rapidez efectuamos estas operaciones mediante desplazamientos, y no como multiplicaciones per se.
Es quizás necesario hacer una especial mención a las dos últimas líneas del código. A fin de modificar únicamente el bit deseado en cada momento, lo editamos mediante el uso de una máscara. Así, si se determina que debe ser un 1, se produce:
if(unos>umbral)dstImg[i][j>>3] |= 0x80>>(j%8);
Donde las coordenadas del píxel considerado son (i,j). En suma, este píxel pertenece al byte[i][j/8], y su posición dentro del mismo será desde la izquierda el resto de j/8. Realizamos por tanto un OR del byte actual con una máscara con un 1 en la posición del píxel considerado, de forma que su valor quede en 1 sin variar el de los demás en el byte.
Código de medianFilter y getUnos.
No hay comentarios:
Publicar un comentario