análisis matemático de rutinas de procesamiento de imágenes

64
José Díaz de Greñu de Pedro Julio Rubio García Facultad de Ciencias, Estudios Agroalimentarios e Informática Grado en Matemáticas 2013-2014 Título Director/es Facultad Titulación Departamento TRABAJO FIN DE GRADO Curso Académico Análisis matemático de rutinas de procesamiento de imágenes digitales en Fiji/ImageJ Autor/es

Upload: dangnhan

Post on 14-Feb-2017

221 views

Category:

Documents


4 download

TRANSCRIPT

Page 1: Análisis matemático de rutinas de procesamiento de imágenes

José Díaz de Greñu de Pedro

Julio Rubio García

Facultad de Ciencias, Estudios Agroalimentarios e Informática

Grado en Matemáticas

2013-2014

Título

Director/es

Facultad

Titulación

Departamento

TRABAJO FIN DE GRADO

Curso Académico

Análisis matemático de rutinas de procesamiento de imágenes digitales en Fiji/ImageJ

Autor/es

Page 2: Análisis matemático de rutinas de procesamiento de imágenes

© El autor© Universidad de La Rioja, Servicio de Publicaciones, 2014

publicaciones.unirioja.esE-mail: [email protected]

Análisis matemático de rutinas de procesamiento de imágenes digitales enFiji/ImageJ, trabajo fin de grado

de José Díaz de Greñu de Pedro, dirigido por Julio Rubio García (publicado por la Universidad de La Rioja), se difunde bajo una Licencia

Creative Commons Reconocimiento-NoComercial-SinObraDerivada 3.0 Unported. Permisos que vayan más allá de lo cubierto por esta licencia pueden solicitarse a los

titulares del copyright.

Page 3: Análisis matemático de rutinas de procesamiento de imágenes

Facultad

Facultad de Ciencias, Estudios Agroalimentarios e Informática

Titulación

Grado en Matemáticas

Título

Análisis Matemático de rutinas de procesamiento de imágenes

digitales en Fiji/ImageJ

Autor/es

José Díaz de Greñu de Pedro

Tutor/es

Julio Jesús Rubio García

Departamento

Matemáticas y Computación

Curso académico

2013-2014

Page 4: Análisis matemático de rutinas de procesamiento de imágenes
Page 5: Análisis matemático de rutinas de procesamiento de imágenes

Resumen

En este trabajo estudiamos cuatro algoritmos de la aplicacion para analisisy procesamiento de imagenes ImageJ. En concreto, damos una descripcionmatematica del filtro de Gauss, de dos algoritmos de thresholding (el deHuang, y el Isodata) y del procedimiento para encontrar maximos localesFindMaxima. Analizamos en detalle la implementacion de estos procesos enJava comprobando la correccion de los mismos y proponiendo algunas mejo-ras. Tambien enumeramos las aplicaciones de estos metodos y presentamosalgunos ejemplos concretos de sus usos por el Grupo de Investigacion enInformatica de la Universidad de La Rioja.

Abstract

In this paper we study four algorithms from the image processing and anal-ysis application ImageJ. Specifically, we give a mathematical description ofthe Gaussian filter, of two thresholding algorithms (Huang and Isodata) andof FindMaxima, a procedure to find local maxima. We analyze in detailthe implementation of these procedures in Java studying its correctness andproposing some improvements. We also list the aplications of these meth-ods and we give some particular examples of their using by the Grupo deInvestigacion en Informatica de la Universidad de La Rioja.

Page 6: Análisis matemático de rutinas de procesamiento de imágenes
Page 7: Análisis matemático de rutinas de procesamiento de imágenes

Indice general

1 Introduccion 1

2 Filtro de Gauss 92.1 Descripcion matematica . . . . . . . . . . . . . . . . . . . . . 92.2 Analisis del algoritmo en ImageJ . . . . . . . . . . . . . . . . 13

2.2.1 Calculo del filtro de Gauss . . . . . . . . . . . . . . . . 172.2.2 Aplicacion del filtro a cada lınea . . . . . . . . . . . . . 20

2.3 Aplicaciones teoricas . . . . . . . . . . . . . . . . . . . . . . . 222.4 Aplicaciones al tratamiento de imagenes biomedicas . . . . . . 23

3 Algoritmos de Thresholding 253.1 Algoritmo de Huang . . . . . . . . . . . . . . . . . . . . . . . 25

3.1.1 Descripcion matematica . . . . . . . . . . . . . . . . . 253.1.2 Analisis del algoritmo en ImageJ . . . . . . . . . . . . 27

3.2 IsoData y algoritmo de Threshold por defecto . . . . . . . . . 303.2.1 Descripcion matematica . . . . . . . . . . . . . . . . . 303.2.2 Analisis del algoritmo en ImageJ . . . . . . . . . . . . 30

3.3 Aplicaciones teoricas . . . . . . . . . . . . . . . . . . . . . . . 343.4 Aplicaciones al tratamiento de imagenes biomedicas . . . . . . 34

4 Algoritmo FindMaxima 374.1 Analisis del algoritmo en ImageJ . . . . . . . . . . . . . . . . 38

4.1.1 Obtencion de los maximos locales . . . . . . . . . . . . 434.1.2 Analisis de los maximos y algoritmo de llenado . . . . 45

4.2 Aplicaciones teoricas . . . . . . . . . . . . . . . . . . . . . . . 524.3 Aplicaciones al tratamiento de imagenes biomedicas . . . . . . 52

Conclusiones 55

Referencias 56

Page 8: Análisis matemático de rutinas de procesamiento de imágenes
Page 9: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 1

Introduccion

El modo de desarrollo de aplicaciones informaticas ha conocido un profundocambio a lo largo del siglo XXI. Se ha pasado de un entorno centralizado, enel que los programas eran monolıticos y en muchas ocasiones escritos desdecero por un unico equipo de programadores, a otro en el que el programadordispone de innumerables recursos de forma que basta con anadir unas pocaslıneas en un complejo framework o encontrar una librerıa adecuada paraconseguir el efecto buscado.

Por supuesto, a esta situacion se ha llegado por medio de una evolu-cion. El papel esencial de los subprogramas fue reconocido desde el principiode la ciencia de la programacion, y de hecho siguen presentes y han sidofundamentales en los sucesivos paradigmas de programacion (programacionestructurada, orientada a objetos, dirigida por eventos, etc.). Es indiscutibleque el uso de librerıas, que no son mas que conjuntos de subrutinas que seponen a disposicion de otros programas, fue fundamental en muchos de losdesarrollos software del siglo XX y que las APIs (Aplication ProgrammingInterfaces), que permiten exportar la funcionalidad de un servicio facilitan-do ası la interconexion de distintos sistemas, comenzaron a ser desarrolladashace ya algunas decadas y hoy en dıa existen para practicamente cualquierservicio.

El uso actual de programas y librerıas desarrollados por terceros (diferen-tes de las personas que reclaman o usaran el sistema software, y tambien de losdesarrolladores del mismo) ha recibido un impulso cualitativo y cuantitativoen los ultimos anos. Frente a las ventajas evidentes de esta nueva tenden-cia (solo hay que pensar, por ejemplo, en lo sencillo que resulta desarrollaraplicaciones para moviles utilizando SDKs (Software Development Kits), de-sentendiendose de multiples detalles tecnicos, relacionados con la interaccioncon el usuario, etc.), se hacen patentes tambien ciertas debilidades. Aparecendudas sobre la correccion del software utilizado como base, sobre su estabili-

1

Page 10: Análisis matemático de rutinas de procesamiento de imágenes

2

dad a lo largo del tiempo, la eficacia y la calidad del codigo, e incluso sobreque hacen realmente los programas. Esto es debido a documentaciones po-bres, y, en general, a un abuso de los foros de “expertos” que dan informacionparcial y que fomentan el “prueba primero y despues ya pensaras (si hacefalta)”junto a usuarios mas preocupados de que el programa funcione aquı yahora que de la correccion general del mismo.

Un caso extremo de la situacion antes descrita es el de los sistemas (oplataformas o entornos) que van creciendo gracias a un esfuerzo colaborativo,en el que multiples participantes contribuyen con sus componentes o plugins.Uno de esos sistemas es ImageJ/Fiji [1]. Se trata de un sistema de softwarelibre, basado en Java, para el analisis y procesamiento de imagenes, que esampliamente utilizado por investigadores en Ciencias de la Vida.

ImageJ tiene algunas caracterısticas que lo hacen especialmente intere-sante como objeto de estudio en el contexto antes presentado. Por una parte,muchos de los plugins han sido desarrollados por investigadores sin una for-macion especıfica en informatica (son biologos, medicos, etc.), lo que haceque el codigo desarrollado, en principio, pueda plantear mas dudas que enotros proyectos de software libre. Por otra, muchas de las aplicaciones finalesque utilizan ImageJ como herramienta pertenecen al area biomedica, por loque los aspectos relacionados con la correccion y la fiabilidad del softwareparecen especialmente sensibles.

El objetivo de este Trabajo Fin de Grado es estudiar las matematicas quesubyacen en algunos de los algoritmos presentes en ImageJ, ası como analizarsu reflejo en los programas correspondientes, para dar una descripcion ma-tematica precisa en el caso de algoritmos para los que no se ha encontrado,o concretar a partir de la implementacion en ImageJ las matematicas de losdistintos artıculos en los que se han basado. Esto constituye un primer pasopara poder, por una parte, conocer que hacen exactamente esos plugins deterceros y, por otra, conocer su grado de correccion y, en su caso, proponermejoras que hagan los programas mas fiables o eficientes.

Puesto que ImageJ es un sistema grande (en cuanto a numero de lıneas decodigo y en cuanto a los temas sobre los que puede aplicarse) hemos centradonuestro estudio en los algoritmos que han sido mas utilizados por el Grupo deInvestigacion en Informatica de la Universidad de La Rioja, en un proyectoconjunto con un equipo de biologos, dirigido por Miguel Morales, que buscanfarmacos para paliar enfermedades neurodegenerativas, como el Alzheimer[2].

Concretamente, la memoria que sigue ha sido organizada segun el estu-dio de una serie de algoritmos, cada uno de los cuales es analizado con lamisma estructura: descripcion matematica, analisis del algoritmo en ImageJ,aplicaciones teoricas, y aplicaciones al tratamiento de imagenes biomedicas.

Page 11: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 1. Introduccion 3

En ocasiones, tambien proponemos mejoras en la implementacion, cuandohemos detectado aspectos manifiestamente mejorables. Los algoritmos estu-diados han sido: filtro de Gauss (utilizado para reducir el ruido en la imagenantes de aplicar otros algoritmos), algoritmos de thresholding (o umbraliza-cion) como el de Huang, el IsoData y el “Default”(utilizados para distinguirlos objetos de interes del fondo), y por ultimo el algoritmo FindMaxima(que ha sido utilizado para determinar la componentes conexas de imagenesdigitales).

Antes de estudiar los algoritmos, vamos a realizar algunos comentariossobre ImageJ y a dar una descripcion matematica de algunos conceptos queutilizaremos a lo largo de este Trabajo Fin de Grado.

Sobre ImageJ

En las distintas secciones de analisis de la implementacion de los diversosalgoritmos en ImageJ se mostraran fragmentos de codigo de la version anali-zada, la mas reciente disponible durante la escritura de este trabajo: ImageJ148t. Dichos fragmentos se muestran con las lıneas numeradas conservandoel numero de lınea del codigo original, aunque por claridad y brevedad sehan omitido numerosas lıneas no relacionadas con el propio algoritmo (lasencargadas de interactuar con el usuario, mostrar debug, algunos metodosque se conservan solo por retro compatibilidad, etc.) ası como numerososcomentarios.

Durante el analisis de los distintos algoritmos se comentara muy detalla-damente el codigo de cada uno, sin embargo conviene conocer los siguientesconceptos que comentamos brevemente a continuacion por ser comunes enImageJ y no relacionados con ningun algoritmo en concreto. Se puede con-sultar [3] para una explicacion mas amplia.

Las imagenes digitales que se estudian son imagenes matriciales (tam-bien llamadas mapas de bits) de resolucion estatica. Dichas imagenes estanformadas por un conjunto de pıxeles ordenados para cada uno de los cualesse guarda informacion sobre brillo, color, etc. Una imagen digital en coloresta formada por varios canales cada uno de los cuales recoge la escala degrises para un color primario. Por ejemplo, el formato RGB posee tres ca-nales que almacenan la escala de grises correspondiente al rojo, verde y azulrespectivamente. Las imagenes empleadas por el Grupo de Investigacion sonimagenes en escala de grises de 255 bits, representadas en ImageJ por laclase ByteProcessor . Conviene tener esto en cuenta ya que varios algoritmospresentan pequenas variaciones en funcion del tipo de imagen sobre el que seestan aplicando.

Page 12: Análisis matemático de rutinas de procesamiento de imágenes

4

ImageJ permite seleccionar una region de la imagen para luego aplicaralgun algoritmo (no todos lo permiten) solo a esos pıxeles, en lugar de a laimagen completa. Nos referiremos a esa region como region de interes, ROI,o simplemente region.

Los algoritmos que se analizan estan implementados como plugins inter-nos. Cada plugin esta implementado por una clase en un unico fichero y,aunque existen otros tipos, los estudiados aquı implementan la interfaz Plu-gInFilter que requiere una imagen (es decir, una instancia de ImageProces-sor) como parametro de entrada. Destacar que la ejecucion de estos comienzaen el metodo run(ImageProcessor).

Pasamos ahora a introducir algunos conceptos matematicos que nos serande utilidad a la hora de analizar los distintos algoritmos.

Imagenes digitales

Matematicamente, una imagen digital matricial de M pıxeles de ancho yN pıxeles de alto puede ser representada como una matriz de dimensionesM × N con valores en un conjunto imagen de valores P ⊂ Z, es decir, unaimagen X es una matriz

X = (xuv) ∈MM×N(P) (u, v) ∈ ZM × ZN

El sistema de coordenadas que se usara toma como (0, 0) la esquina superiorizquierda y como (M − 1, N − 1) la esquina inferior derecha. El conjunto devalores P es un subconjunto de Z de la forma 1, 2, ..., L cuyo tamano dependedel formato de la imagen: para imagenes con profundidad de color de n bits,L toma el valor L = 2n. Algunos formatos habituales son imagenes de 8, 16o 32 bits. En este trabajo nos centraremos en imagenes en escala de grisesde 8 bits por ser las que se han utilizado en el Grupo de Investigacion. Portanto cada pıxel xuv ∈ P = Z256 representa la luminosidad o intensidad delpıxel de coordenadas (u, v), siendo 0 la intensidad mınima (negro) y 255 lamaxima (blanco).

Filtros lineales

Un filtro es una operacion que se aplica a una imagen pıxel a pıxel tal quepara calcular el nuevo valor de cada pıxel se usa no solo dicho elemento sinotambien los cercanos. En particular, un filtro lineal sustituye el valor de cadapıxel por una combinacion lineal de los pıxeles de un entorno rectangularcentrado en el.

Page 13: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 1. Introduccion 5

Podemos tomar como representacion matematica de un filtro lineal, unamatriz H con valores en R, de anchura y longitud impares. Para estas ma-trices se establece un sistema de coordenadas donde el elemento central esH(0, 0), por lo que para una matriz de dimensiones (2i + 1) × (2j + 1) loselementos van desde H(−i,−j) hasta H(i, j).

Con estas notaciones, el resultado de aplicar un filtro lineal H a unaimagen X es una nueva imagen X ′ dada por la expresion

X ′(u, v) =∑

(i,j)∈RH

X(u+ i, v + j)H(i, j) ∀ (u, v) ∈ RI (1.1)

donde RH , RI denotan el conjunto de coordenadas del filtro H y de la imagenX respectivamente. Notar que en los bordes de la imagen, el elemento xu+i,v+jpuede no existir si (u+ i, v+ j) esta situado fuera de los lımites de la imagen.Existen distintas tecnicas para evitar este problema, las mas habituales sonreflejar o copiar la imagen original, o usar los pıxeles del borde de la imagenmas de un vez, como veremos mas adelante.

Convolucion

La nocion matematica asociada a la aplicacion de filtros es la convoluciondiscreta en dos dimensiones1. Dadas dos funciones 2-dimensionales discretasI y H se define la convolucion I ′ = I ∗H como

I ′(u, v) =∞∑

i=−∞

∞∑j=−∞

I(u− i, v − j)H(i, j) ∀ (u, v) ∈ Z2 (1.2)

No obstante, existen dos problemas a la hora de adaptar esta definicion a laaplicacion de filtros de imagenes:

• La operacion convolucion 2-dimensional discreta se aplica sobre dosfunciones discretas con dominio en todo Z2 obteniendo una nueva fun-cion con el mismo dominio; pero las imagenes y los filtros son matricesfinitas.

1 En analisis funcional, la convolucion es un operador definido en un espacio de medidacomo sigue.

Definicion. Sean f, g : Rn → C funciones medibles. Se define su convolucion como

(f ∗ g)(x) =

∫Rn

f(x− y)g(y) dy

En este apartado se consideran solo convoluciones discretas de dos dimensiones, por susaplicaciones al analisis de imagenes digitales.

Page 14: Análisis matemático de rutinas de procesamiento de imágenes

6

Para resolverlo, simplemente consideraremos funciones discretas defini-das a partir de las matrices finitas sin mas que asignar a cada (i, j) ∈ Z2

la entrada de la matriz de coordenadas (i, j) o 0 si las coordenadas nose corresponden a un elemento de la matriz.

De la misma forma, a partir de la funcion I ′ obtenida con la convolucion,construiremos una matriz finita (que corresponde a la nueva imagende dimensiones M × N) sin mas que tomar el subconjunto imagenI ′({0, ..., N − 1} × {0, ...,M − 1}).

• Notar que existe una diferencia de signos en las variables i, j entre lasformulas (1.1) y (1.2). Podemos escribir la convolucion de otra forma

I ′(u, v) =∞∑

i=−∞

∞∑j=−∞

I(u− i, v − j)H(i, j)

=∞∑

i=−∞

∞∑j=−∞

I(u+ i, v + j)H(−i,−j)

=∞∑

i=−∞

∞∑j=−∞

I(u+ i, v + j)H∗(i, j)

donde usamos la funcion filtro invertida H∗(i, j) = H(−i,−j). De estemodo, aplicar un filtro H a una imagen I es equivalente a la convolucionI ∗H∗; en particular, en los filtros simetricos (como el gaussiano) no esnecesario tener en cuenta esta consideracion.

Una vez asociado el operador matematico convolucion a la aplicacion defiltros a imagenes, podemos aprovechar algunos resultados que se deducen.

Separabilidad

Una propiedad basica de las convoluciones lineales es la separabilidad. Si unfiltro H puede ser expresado como H = H1 ∗H2, entonces se tiene que

I ∗H = (I ∗H1) ∗H2

Para demostrar esta igualdad basta con aplicar la definicion y reordenarconvenientemente

Page 15: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 1. Introduccion 7

(I ∗H1) ∗H2 =

(∞∑

i=−∞

∞∑j=−∞

I(u− i, v − j) H1(i, j)

)∗H2(u, v)

=∞∑

k=−∞

∞∑l=−∞

∞∑i=−∞

∞∑j=−∞

I(u− i− k, v − j − l) H1(i, j) H2(k, l)

∗=

∞∑i=−∞

∞∑j=−∞

I(u− i, v − j)∞∑

k=−∞

∞∑l=−∞

H1(i− k, j − l)H2(k, l)

=∞∑

i=−∞

∞∑j=−∞

I(u− i, v − j) H(i, j)

= I ∗H

donde en * se han desplazado los ındices de forma que (i, j) 7→ (i− k, j − l)(esto no afecta a los lımites de los sumatorios dado que estos son sobre todoslos enteros).

En el caso de aplicaciones de filtros lineales a imagenes, esto es especial-mente util cuando podemos expresar una funcion (asociada a un filtro lineal)H(x, y) a partir de funciones discretas de una variable H1, H2 de forma que

H(x, y) = H1(x) ∗H2(y) ∀ (x, y)

ya que en tal caso, podemos calcular el resultado de aplicar dicho filtro lineala una imagen I como

I ′ = (I ∗H1) ∗H2 (1.3)

en lugar deI ′ = I ∗H (1.4)

Esta propiedad se conoce como x/y-separabilidad del filtro, y proporcionaimportantes ahorros de coste computacional: si I es una imagen de dimen-siones w × h y H un filtro lineal cuya matriz asociada tiene dimensiones(2M + 1)× (2N + 1), el coste computacional de (1.4) es O(whMN) mientrasque el de (1.3) es O(wh(M +N)), lo que supone reducir una complejidad enprincipio cuadratica (en las dimensiones del filtro) a solo lineal.

Page 16: Análisis matemático de rutinas de procesamiento de imágenes
Page 17: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 2

Filtro de Gauss

El filtro de Gauss (o Gaussiano) es un filtro de suavizado1 ampliamente uti-lizado en software de edicion de imagenes digitales para reducir el ruido odisminuir la nitidez. En analisis de imagenes digitales tambien es util dadoque, al eliminar detalles de la imagen, las estructuras destacan mas. Reci-be este nombre porque se basa en la funcion de Gauss como detallamos acontinuacion.

2.1 Descripcion matematica

La matriz que se identifica con este filtro es la asociada a la funcion Gaussiana2-dimensional

Gσ(x, y) = exp

(−x

2 + y2

2σ2

)(2.1)

donde σ > 0 es un parametro que denota la desviacion estandar. Esta matrizsimetrica respecto a la componente (0, 0) se caracteriza porque dicha com-ponente tiene el peso mas importante, y el resto decaen rapidamente haciacero segun se alejan del centro.

La importancia del peso del elemento central y la velocidad con la queel resto de pesos decaen es mayor cuanto menor es σ, por tanto la imagenfinal obtenida es mas borrosa cuanto mayor es σ. Las dimensiones de la ma-triz asociada a este filtro lineal tambien vienen dadas por este parametroya que, a pesar de que Gσ(x, y) > 0 ∀x, y (lo que requerirıa una matrizinfinita), las componentes {(x, y) |

√x2 + y2 > 3σ} son suficientemente pe-

quenas como para ser despreciadas en implementaciones, por lo que basta

1 Se llaman filtros de suavizado a los lineales cuyas matrices asociadas contienen exclu-sivamente elementos positivos, ya que estos filtros disminuyen la diferencia entre valoresde pıxeles adyacentes.

9

Page 18: Análisis matemático de rutinas de procesamiento de imágenes

10 2.1. Descripcion matematica

tomar una matriz de dimensiones tales que se incluyen todos los elementosno despreciables2.

Otra propiedad caracterıstica del filtro de Gauss es la isotropıa: el filtrotrata de la misma forma todas las direcciones. Es facil ver que la expresion(2.1) es invariante por giros, ya que tomando

(x0, y0) =

(cosα sinα− sinα cosα

)(x, y) = (x cosα− y sinα, x sinα + y cosα)

se tiene que

Gσ(x0, y0) = exp

(−(x cosα− y sinα)2 + (x sinα + y cosα)2

2σ2

)=

= exp

(−x

2 + y2

2σ2

)= Gσ(x, y) ∀α ∈ [0, 2π]

Esto garantiza que una imagen a la que se le aplica el filtro de Gauss sesuaviza de la misma forma en todas las direcciones. En particular es invariablepor un giro de π radianes, por lo que no tendremos que preocuparnos pordiferenciar entre H y H∗ (matrices asociadas al filtro que se definieron en laintroduccion) cuando utilicemos la convolucion para aplicar este filtro.

Notar que el filtro de Gauss dado por la formula (2.1) no esta normalizadoya que ∫

R2

Gσ(x, y) dA = 2πσ2 6= 1

La normalidad es una propiedad deseable en los filtros ya que mantiene losvalores de los pıxeles en el mismo rango, evitando ası aclarar u oscurecer laimagen globalmente e incluso obtener valores no pertenecientes al dominiode validez de la imagen (esto ultimo solo puede suceder si el valor de laintegral es mayor que la unidad). Para evitar estos inconvenientes basta conintroducir un factor adecuado

Gσ(x, y) =1

2πσ2exp

(−x

2 + y2

2σ2

)(2.2)

Esta sera la expresion para el filtro de Gauss que se usara en la implementa-cion, cuya matriz asociada H (al menos la infinita) cumplira∑

i,j

H(i, j) = 1

2El valor 3σ es conveniente como tamano del filtro pero, como veremos en la implemen-tacion, el tamano optimo varıa en funcion de la precision con la que queramos trabajar.

Page 19: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 2. Filtro de Gauss 11

En la practica, habitualmente, se tiene que∑

i,j H(i, j) ≤ 1 (aunque convalores muy cercanos) ya que, como hemos visto anteriormente, se desprecianlas componentes suficientemente pequenas del filtro para poder obtener unamatriz finita. Aun ası, se mantiene la garantıa de que el valor obtenido sera unvalor valido en el dominio de la imagen, por lo que no es necesaria ningunacomprobacion sobre los valores de la imagen tras aplicar filtros normalizados.

x/y-Separabilidad del filtro de Gauss

A partir de la expresion (2.1) es inmediato que el filtro de Gauss es x/y-separable debido a las propiedades de la funcion exponencial

Gσ(x, y) = exp

(−x

2 + y2

2σ2

)=

= exp

(− x2

2σ2

)exp

(− y2

2σ2

)=

= gσ(x) gσ(y)

donde

gσ(x) = exp

(− x2

2σ2

)(2.3)

es la version unidimensional del filtro de Gauss.Por ello basta con aplicar a la imagen el filtro unidimensional gσ(x) dos

veces, una en cada eje, para obtener el mismo resultado, beneficiandonos delos ahorros computacionales que esto supone.

Correccion de los bordes

Como hemos visto, a la hora de calcular el filtro, tomaremos un tamano Rdependiente de σ y usaremos la formula (2.3) para calcular las componentesdel filtro. Sin embargo, truncar la funcion a cero directamente para valoressuperiores al tamano del filtro, introduce una discontinuidad que puede con-llevar la aparicion de artefactos3 en la imagen. Para evitar este problema,se puede tomar un polinomio como transaccion entre el filtro de Gauss y lafuncion constante 0 para conseguir una funcion suave (derivable). Esta for-mulacion matematica, que no hemos encontrado explicada en ningun artıculocientıfico, ha sido deducida examinando el codigo Java que se analizara en lasiguiente seccion.

3Un artefacto es una distorsion no deseada apreciable en la imagen.

Page 20: Análisis matemático de rutinas de procesamiento de imágenes

12 2.1. Descripcion matematica

Sea p(x) un polinomio de segundo grado que se anule en la dimension delfiltro y sea derivable tanto en el punto de contacto con la funcion gaussiana(aun por determinar, sea este punto x = r, 0 < r < R) como en x = R(zona de paso a la funcion constante 0. Por tanto, siendo p(x) = ax2 + bx+ c,se busca encontrar el punto de contacto r y el polinomio p(x) (es decir, lasvariables a, b, c) a partir del siguiente sistema

p(r) = f(r)

p′(r) = f ′(r)

p(R) = 0

p′(R) = 0

(2.4)

Procedemos a resolver este sistema. En primer lugar, podemos simplificarla forma del polinomio p(x) y tomarlo como p(x) = a2(x− R)2, ya que estaes la forma general de un polinomio de segundo grado cumpliendo las dosultimas condiciones del sistema. De la primera condicion, se tiene

p(r) = f(r) =⇒ a2(r −R)2 =⇒ a =

√f(r)

R− r(R > r) (2.5)

Para terminar, veamos que minimizando a(r), conseguimos la segundacondicion del sistema (2.4) (este es el metodo que sigue ImageJ en el codigopara la resolucion del sistema, como veremos mas adelante), es decir

a′(r) = 0 =⇒ f ′(r) = p′(r)

Para ello, calculemos la derivada de a(r) segun (2.5)

a′(r) =f ′(r)

2(R− r)√f(r)

+

√f(r)

(R− r)2

Ası,

a′(r) = 0 =⇒ f ′(r)

2(R− r)√f(r)

=−√f(r)

(R− r)2=⇒ f ′(r) =

−2f(r)

R− r

Por otro lado, p′(x) = −2a2(R− x), sustituyendo x = r y a = a(r)

p′(r) =−2f(r)

R− r= f ′(r)

obteniendo la igualdad que querıamos justificar.

Page 21: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 2. Filtro de Gauss 13

2.2 Analisis del algoritmo en ImageJ

En esta seccion analizaremos el codigo correspondiente al plugin del filtro deGauss implementado en el fichero GaussianBlur.java. En primer lugar vamosa dar una idea general de que pasos se siguen y que metodos intervienen ala hora de aplicar el filtro para despues analizar con mas detalle cada paso.

El proceso comienza con la llamada al metodo run(), que tras ajustar al-gunos parametros, invoca a blurGaussian() que aplicara el filtro a la imagen.Para ello, se invoca a blurFloat() sobre cada canal de la imagen, despues res-taura algunos pıxeles que podrıan haber sido modificados fuera de la regionseleccionada de la imagen (mas adelante veremos como y por que). blur-Float() aplica el filtro de Gauss en cada canal de la imagen, para ello aplicael filtro unidimensional en el eje X y luego en el eje Y mediante la funcionblur1Direction(). Esta funcion utiliza el vector calculado por makeGaussian-Kernel() y para distribuir la operacion de convolucion entre distintos hilosusando convolveLine().

Vamos a detenernos ahora en cada metodo, comenzando por run():

Metodo run (punto de entrada del plugin)

121 public void run(ImageProcessor ip) {

122 double sigmaX = sigmaScaled ? sigma/imp.

getCalibration ().pixelWidth : sigma;

123 double sigmaY = sigmaScaled ? sigma/imp.

getCalibration ().pixelHeight : sigma;

124 double accuracy = 0.002;

126 Rectangle roi = ip.getRoi ();

127 blurGaussian(ip , sigmaX , sigmaY , accuracy);

128 }

Como se aprecia en el codigo, se encarga de reescalar σ adecuadamen-te4, fijar una precision en funcion del tipo de imagen con el que estemostrabajando y por ultimo invoca a blurGaussian(), metodo que analizamos acontinuacion:

Metodo blurGaussian

154 public void blurGaussian(ImageProcessor ip , double sigmaX

, double sigmaY , double accuracy) {

4Habitualmente, se asume que las unidades en las que se especifica σ son pıxeles. Sinembargo, ImageJ permite definir una escala para la imagen y tomar σ en unidades demedida como micras.

Page 22: Análisis matemático de rutinas de procesamiento de imágenes

14 2.2. Analisis del algoritmo en ImageJ

155 boolean hasRoi = ip.getRoi ().height !=ip.getHeight ()

&& sigmaX >0 && sigmaY >0;

156 if (hasRoi && !calledAsPlugin)

157 ip.snapshot ();

160 FloatProcessor fp = null;

161 for (int i=0; i<ip.getNChannels (); i++) {

162 fp = ip.toFloat(i, fp);

163

164 blurFloat(fp, sigmaX , sigmaY , accuracy);

165

166 ip.setPixels(i, fp);

167 }

168 if (hasRoi)

169 resetOutOfRoi(ip, (int)Math.ceil (5* sigmaY));

170 return;

171 }

Simplemente se aplica el metodo blurFloat() a cada canal de la imagen.Tambien restaura los pıxeles fuera de la region de interes usando resetOutO-fRoi (no estudiaremos esa funcion con detalle, pero basta saber que restauran lıneas fuera de la region de interes, donde n es su segundo parametro). Estoes necesario porque algunas de esas lıneas (fuera de la region de interes) seranmodificadas como vamos a ver tras analizar el siguiente metodo, blurFloat().

Metodo blurFloat

183 public void blurFloat(FloatProcessor ip , double sigmaX ,

double sigmaY , double accuracy) {

184 if (sigmaX > 0)

185 blur1Direction(ip , sigmaX , accuracy , true , (int)

Math.ceil (5* sigmaY));

186

187 if (sigmaY > 0)

188 blur1Direction(ip , sigmaY , accuracy , false , 0);

189 return;

190 }

Para aplicar el filtro de Gauss a la imagen, emplea la x/y-separabilidad,aplicando el filtro de Gauss unidimensional primero al eje X, y luego al eje Y.Notar que para que la x/y-separabilidad funcione correctamente, todo pıxelusado en la convolucion en la direccion Y ha tenido que ser tratado en ladireccion X, por tanto cuando se aplica la convolucion en el eje X, hay quetratar algunas lıneas mas, y no solo las de la region de interes. Esto hace quesea necesario resetear los pıxeles cercanos a la region de interes, como vimos

Page 23: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 2. Filtro de Gauss 15

en la funcion anterior.

Vamos a ver ahora como se aplica el filtro de Gauss en un eje, sin embargono vamos a estudiar en detalle la optimizacion5 que se usa para σ > 8,5. Tam-bien se ha omitido parte del codigo que distribuye el proceso entre distintoshilos, ya que no supone una modificacion del algoritmo.

Metodo blur1Direction

200 public void blur1Direction( final FloatProcessor ip ,

final double sigma , final double accuracy ,

201 final boolean xDirection , final int extraLines) {

202

203 final int UPSCALE_K_RADIUS = 2;

204 final double MIN_DOWNSCALED_SIGMA = 4.;

205 final float [] pixels = (float [])ip.getPixels ();

206 final int width = ip.getWidth ();

207 final int height = ip.getHeight ();

208 final Rectangle roi = ip.getRoi ();

209 final int length = xDirection ? width : height;

210 final int pointInc = xDirection ? 1 : width;

211 final int lineInc = xDirection ? width : 1;

212 final int lineFromA = (xDirection ? roi.y : roi.x) -

extraLines;

213 final int lineFrom;

214 if (lineFromA < 0) lineFrom = 0;

215 else lineFrom = lineFromA;

216 final int lineToA = (xDirection ? roi.y+roi.height :

roi.x+roi.width) + extraLines;

217 final int lineTo;

218 if (lineToA > (xDirection ? height:width)) lineTo = (

xDirection ? height:width);

219 else lineTo = lineToA;

220 final int writeFrom = xDirection? roi.x : roi.y;

221 final int writeTo = xDirection ? roi.x+roi.width :

roi.y+roi.height;

225 final int numThreads = Math.min(Prefs.getThreads (),

lineTo -lineFrom);

229 final boolean doDownscaling = sigma > 2*

MIN_DOWNSCALED_SIGMA + 0.5;

230 final int reduceBy = doDownscaling ?

5Los valores de σ de nuestro interes son mucho menores por lo que esta optimizacion notoma lugar. La idea general es re-escalar la imagen reduciendo su tamano, aplicar el filtrode Gauss, y volver ampliar la imagen, teniendo en cuenta que esta ultima operacion dere-escalado tambien hace que la imagen pierda nitidez, y ajustando σ convenientemente.

Page 24: Análisis matemático de rutinas de procesamiento de imágenes

16 2.2. Analisis del algoritmo en ImageJ

231 Math.min((int)Math.floor(sigma/

MIN_DOWNSCALED_SIGMA), length)

232 : 1;

237 final double sigmaGauss = doDownscaling ?

238 Math.sqrt(sigma*sigma/( reduceBy*reduceBy) -

1./3. - 1./4.)

239 : sigma;

240 final int maxLength = doDownscaling ?

241 (length+reduceBy -1)/reduceBy + 2*(

UPSCALE_K_RADIUS + 1)

242 : length;

243 final float [][] gaussKernel = makeGaussianKernel(

sigmaGauss , accuracy , maxLength);

244 final int kRadius = gaussKernel [0]. length*reduceBy;

245 final int readFrom = (writeFrom -kRadius < 0) ? 0 :

writeFrom -kRadius;

246 final int readTo = (writeTo+kRadius > length) ?

length : writeTo+kRadius;

247 final int newLength = doDownscaling ?

248 (readTo -readFrom+reduceBy -1)/reduceBy + 2*(

UPSCALE_K_RADIUS + 1)

249 : length;

250 final int unscaled0 = readFrom - (UPSCALE_K_RADIUS +

1)*reduceBy;

253 final float [] downscaleKernel = doDownscaling ?

makeDownscaleKernel(reduceBy) : null;

254 final float [] upscaleKernel = doDownscaling ?

makeUpscaleKernel(reduceBy) : null;

256 for ( int t = 0; t < numThreads; ++t ) {

257 final int ti = t;

262 new Runnable () {

266 int pixel0 = (lineFrom+ti)*lineInc;

267 for (int line=lineFrom + ti; line <lineTo; line +=

numThreads , pixel0 += numThreads*lineInc) {

275 if (doDownscaling) {

276 downscaleLine(pixels , cache1 , downscaleKernel , reduceBy ,

pixel0 , unscaled0 , length , pointInc , newLength);

277 convolveLine(cache1 , cache2 , gaussKernel , 0, newLength ,

1, newLength -1, 0, 1);

278 upscaleLine(cache2 , pixels , upscaleKernel , reduceBy ,

pixel0 , unscaled0 , writeFrom , writeTo , pointInc);

279 } else {

280 int p = pixel0 + readFrom*pointInc;

Page 25: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 2. Filtro de Gauss 17

281 for (int i=readFrom; i<readTo; i++ ,p+= pointInc)

282 cache1[i] = pixels[p];

283 convolveLine(cache1 , pixels , gaussKernel , readFrom ,

readTo , writeFrom , writeTo , pixel0 , pointInc);

284 }

285 }

286 }

311 return;

312 }

Ademas de calcular los parametros para convolveLine() (que explicare-mos mas adelante), esta funcion distribuye el calculo de la convolucion dela imagen entre numThreads hilos, asignando las lıneas i, numThreads +i, numThreads ∗ 2 + i, ... al hilo i-esimo. Cada hilo copia los pıxeles de lalınea a tratar a una cache que servira como datos de entrada para el metodoconvolveLine(), ya que es necesario disponer de los valores originales de lospıxeles mientras se calcula la convolucion.

Vamos a detallar a continuacion los dos metodos usados por esta funcionque son los fundamentales en la aplicacion del filtro:

2.2.1 Calculo del filtro de Gauss

makeGaussianKernel() se encarga de calcular el vector asociado al filtro deGauss lineal, dados σ (desviacion estandar), la precision para el calculo p yel tamano de dicho vector. La precision es fija para cada tipo de imagen, enconcreto 0,002 para las imagenes que tratamos, y el tamano maximo rara vezlimitara el tamano del vector (solo para imagenes muy pequenas o σ muygrande) por lo que el parametro principal de este metodo es σ.

La primera tarea de la que se encarga esta funcion es calcular que tamanotiene que tener el vector asociado al nucleo de forma que sea lo mas pequenoposible (lo que conlleva menor tiempo de calculo) pero suficientemente grandepara que no halla errores numericos mayores que la precision dada p. Dadoque el filtro es simetrico, solo calcularemos un lado, es decir, las r primerasentradas para nuestro vector de tamano 2r + 1.

Garantizar una precision p es equivalente a poder distinguir entre n = 1p

valores. teniendo en cuenta que el valor mas pequeno de nuestro vector esta enel extremo r, tenemos

exp

(− r2

2σ2

)≤ 1

p

Page 26: Análisis matemático de rutinas de procesamiento de imágenes

18 2.2. Analisis del algoritmo en ImageJ

Aplicando logaritmos y reordenando, obtenemos una inecuacion para r enfuncion de σ, p. Tomando el menor entero que la cumple tenemos

r = dσ√−2 log pe+ 1

correspondiente a la lınea 530 del codigo. Despues se aseguran algunas res-tricciones sobre el radio: por un lado se requiere r ≥ 50 para garantizar unaprecision mınima, por otro lado se garantiza que r no sea mayor que el anchoo largo (segun la direccion que se este procesando) de la imagen.

Metodo makeGaussianKernel, calculo de la dimension

529 public float [][] makeGaussianKernel(final double sigma ,

final double accuracy , int maxRadius) {

530 int kRadius = (int)Math.ceil(sigma*Math.sqrt(-2*Math.

log(accuracy)))+1;

531 if (maxRadius < 50) maxRadius = 50;

532 if (kRadius > maxRadius) kRadius = maxRadius;

533 float [][] kernel = new float [2][ kRadius ];

A continuacion, se calculan las entradas a partir de la formula (2.3) yse aplica la correccion de bordes utilizando (2.5) y minimizando la variablea para encontrar el polinomio y el punto r solucion del sistema (2.4). Porsimplicidad, ImageJ minimiza a sobre los enteros.

Metodo makeGaussianKernel, calculo y correccion de los bordes

534 for (int i=0; i<kRadius; i++)

535 kernel [0][i] = (float)(Math.exp (-0.5*i*i/sigma/

sigma));

536 if (kRadius < maxRadius && kRadius > 3) {

537 double sqrtSlope = Double.MAX_VALUE;

538 int r = kRadius;

539 while (r > kRadius /2) {

540 r--;

541 double a = Math.sqrt(kernel [0][r])/(kRadius -r

);

542 if (a < sqrtSlope)

543 sqrtSlope = a;

544 else

545 break;

546 }

547 for (int r1 = r+2; r1 < kRadius; r1++)

548 kernel [0][r1] = (float)((kRadius -r1)*(kRadius

-r1)*sqrtSlope*sqrtSlope);

549 }

Page 27: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 2. Filtro de Gauss 19

Por ultimo se procede a normalizar el vector. Para ello se calcula la sumade las componentes numericamente si el filtro es suficientemente grande, omediante la integral si el tamano del filtro ha sido truncado por el tamano dela imagen (lo que implicarıa que la suma numerica no serıa exacta). Tambiense devuelve como un segundo vector cuyas entradas son la suma de las com-ponentes restantes del primer vector (esto permite un ahorro computacionalcomo veremos mas adelante en convolveLine()).

Metodo makeGaussianKernel, normalizacion

550 double sum;

551 if (kRadius < maxRadius) {

552 sum = kernel [0][0];

553 for (int i=1; i<kRadius; i++)

554 sum += 2* kernel [0][i];

555 } else

556 sum = sigma * Math.sqrt (2* Math.PI);

557

558 double rsum = 0.5 + 0.5* kernel [0][0]/ sum;

559 for (int i=0; i<kRadius; i++) {

560 double v = (kernel [0][i]/sum);

561 kernel [0][i] = (float)v;

562 rsum -= v;

563 kernel [1][i] = (float)rsum;

564

565 }

566 return kernel;

Podemos especificar el valor devuelto por este metodo como sigue, sean

ki = gσ(i) = exp

(− i2

2σ2

), sum =

k0 + 2

r−1∑i=1

ki si r < maxRadius

∫ ∞−∞

gσ(x) dx = σ√

2π si r ≥ maxRadius

El valor devuelto por la funcion es

makeGaussianKernel(σ) =

k0

sum

k1sum

. . .kr−1sum

rsum−0∑i=0

ki rsum−1∑i=0

ki . . . rsum−r−1∑i=0

ki

Page 28: Análisis matemático de rutinas de procesamiento de imágenes

20 2.2. Analisis del algoritmo en ImageJ

donde

rsum =1

2+

1

2

k0sum

es la suma de las componentes del primer vector6 por tanto el valor devueltoes equivalente a

makeGaussianKernel(σ) =

k0

sum

k1sum

. . .kr−1sum

r−1∑i=0

kisum

r−1∑i=1

kisum

. . . 0

2.2.2 Aplicacion del filtro a cada lınea

Esta funcion es realizada por el metodo convolveLine(), que implementa elcalculo de la convolucion de una lınea de la imagen con el nucleo unidimen-sional del filtro de Gauss calculado anteriormente. Para entender el codigoconviene tener en cuenta los siguientes detalles

• El resultado de la operacion se almacena en la imagen final, pero estemetodo recibe los pıxeles de la imagen en un array unidimensional. Portanto, los pıxeles de una fila estan seguidos, pero los de una columnaestan separados por el ancho de la imagen.

Se usan los parametros point0 y pointInc para determinar que lınea dela imagen se esta escribiendo; en concreto los valores que toman son:

Escritura en la fila i: point0 = i ∗ ancho pointInc = 1Escritura en la columna i: point0 = i pointInc = ancho

• Ademas, se permite operar solo con un fragmento de la lınea (esto esutil si hemos definido una region de interes donde aplicar el filtro que noes la imagen completa). Se usan los parametros writeFrom y writeTopara definir el rango a utilizar: [writeFrom,writeTo)

• Por ultimo, queda por resolver el problema que aparece al calcular cercade los lımites de la lınea, es decir, cuando no se dispone de suficientes

6Notar que 1 =1

sum

(k0 + 2

r−1∑i=1

ki

)y por tanto

rsum =1

2+

1

2

k0sum

=1

2sum

(k0 + 2

r−1∑i=1

ki

)+

1

2

k0sum

=1

sum

r−1∑i=0

ki

Page 29: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 2. Filtro de Gauss 21

pıxeles cercanos para calcular la convolucion. En ImageJ resuelven esteproblema tomando el pıxel lımite (el primero o el ultimo de la lınea)siempre que fuera necesario usar un pıxel fuera de la lınea.

Metodo convolveLine

459 private void convolveLine(float[] input ,float[] pixels ,

float [][] kernel ,int readFrom ,

460 int readTo , int writeFrom , int writeTo , int

point0 , int pointInc) {

461 final int length = input.length;

462 final float first = input [0];

463 final float last = input[length -1];

464 final float [] kern = kernel [0];

465 final float kern0 = kern [0];

466 final float [] kernSum = kernel [1];

467 final int kRadius = kern.length;

468 final int firstPart = kRadius < length ? kRadius

: length;

469 int p = point0 + writeFrom*pointInc;

470 int i = writeFrom;

471 for (; i<firstPart; i++,p+= pointInc) {

472 float result = input[i]*kern0;

473 result += kernSum[i]* first;

474 if (i+kRadius >length) result += kernSum[

length -i-1]* last;

475 for (int k=1; k<kRadius; k++) {

476 float v = 0;

477 if (i-k >= 0) v += input[i-k];

478 if (i+k<length) v+= input[i+k];

479 result += kern[k] * v;

480 }

481 pixels[p] = result;

482 }

483 final int iEndInside = length -kRadius <writeTo ?

length -kRadius : writeTo;

484 for (;i<iEndInside;i++,p+= pointInc) {

485 float result = input[i]*kern0;

486 for (int k=1; k<kRadius; k++)

487 result += kern[k] * (input[i-k] + input[i

+k]);

488 pixels[p] = result;

489 }

490 for (; i<writeTo; i++,p+= pointInc) {

491 float result = input[i]*kern0;

492 if (i<kRadius) result += kernSum[i]* first;

493 if (i+kRadius >= length) result += kernSum[

length -i-1]* last;

494 for (int k=1; k<kRadius; k++) {

Page 30: Análisis matemático de rutinas de procesamiento de imágenes

22 2.3. Aplicaciones teoricas

495 float v = 0;

496 if (i-k >= 0) v += input[i-k];

497 if (i+k<length) v+= input[i+k];

498 result += kern[k] * v;

499 }

500 pixels[p] = result;

501 }

502 }

A partir de estas observaciones, podemos dividir el metodo en cuatrosecciones:

461-470: Se calculan los ındices de los arrays necesarios para operar y hasta don-de llega la primera parte de la convolucion (firstPart). Esta primeraparte contiene los pıxeles que no contienen suficientes puntos anterioresa ellos para calcular la convolucion, por lo que sera necesario usar elprimer pıxel varias veces.

471-482: Se calcula la convolucion para los ındices de la primera parte. Primero seusa el vector que contiene las sumas parciales del nucleo para utilizartantas veces como haga falta el primer pıxel (469) y luego se iterasobre todos los pıxeles cercanos para calcular la convolucion, teniendoen cuenta los que se pueden salir de rango (condicionales de las lıneas473, 474).

483-489: Se calcula donde comienza la parte final (donde hara falta usar el ultimopıxel varias veces) y se calcula la convolucion de los pıxeles en la parteintermedia (para los que no hay ningun problema y basta con aplicarla definicion de convolucion).

490-501: Se calcula la convolucion para los ındices de la ultima parte (muy si-milar al tratamiento de la primera parte)

2.3 Aplicaciones teoricas

El filtro de Gauss es un filtro de suavizado por lo que tiende a suavizar oemborronar las imagenes a las que es aplicado.

Como hemos visto, este filtro concede mucho mas peso a los pıxeles cuantomas cercanos al pıxel central estan (a diferencia de otros filtros de suaviza-do como el de la media, que trata de la misma manera a todos los pıxelescercanos) lo que hace que preserve los bordes mejor. Por otro lado, al embo-rronar la imagen disminuye el ruido que pudiera haber a lo largo de la misma

Page 31: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 2. Filtro de Gauss 23

igualando los pıxeles cercanos. Estas dos propiedades hacen que sea usadofrecuentemente para preparar las imagenes antes de aplicar un algoritmo dedeteccion de bordes.

Este filtro tambien es usado antes de reducir las dimensiones de unaimagen para evitar aliasing7, ya que elimina informacion con alta frecuenciaque pudiera existir en la imagen original, evitando que se intensifique en laimagen reescalada; ademas al ser una funcion suave no introduce artefactosen forma de anillo en la imagen.

2.4 Aplicaciones al tratamiento de imagenes

biomedicas

La imagen final que se estudia se ve afectada por diversos agentes externos,bien debido a la preparacion de la muestra o bien al modo de adquirir laimagen. Es decir, una imagen puede tener ruido, debido a fluctuaciones de laluz o estructuras que aparecen en el momento de su adquisicion. Tambien sepuede ver afectada por la baja resolucion del microscopio o porque la muestrano posee una perfecta distribucion del colorante y puede provocar que laimagen no tenga un contraste homogeneo. De cualquier manera, para intentarmejorar la imagen y hacer que estos inconvenientes afecten al resultado finalen menor medida, es habitual el uso de los filtros.

Para mejorar la imagen y contrarrestar estos efectos, el Grupo de In-formatica usa el filtro de Gauss, ya que evita picos de intensidad y homoge-neiza su luminosidad. Este filtro particularmente, se ha usado en el plugindesarrollado por el Grupo de Informatica para ImageJ, NeuronZigzagJ [2].Esta tecnica es comunmente utilizada como paso previo a la realizacion deuna segmentacion de la imagen (tecnicas de umbralizacion), puesto que estepaso ayuda a homogeneizar y eliminar el ruido de la imagen que puede influiren el calculo de un umbral.

7Se denomina aliasing al efecto causante de que dos senales distintas continuas o dealta frecuencia sean representadas por una misma senal con frecuencia menor al realizarun muestreo.

Page 32: Análisis matemático de rutinas de procesamiento de imágenes

24 2.4. Aplicaciones al tratamiento de imagenes biomedicas

De izquierda a derecha, imagen original (dendrita de una neurona de hipocampo de uncultivo transfectado con Actina-GFP) y resultados de aplicar el filtro de Gauss con σ = 2(imagen central) y σ = 5.

Veremos la diferencia en los resultados que se obtienen habiendo aplicadoeste filtro antes de utilizar otros procedimientos en el apartado de aplicacionesal tratamiento de imagenes biomedicas de los siguientes algoritmos.

Page 33: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 3

Algoritmos de Thresholding

Los algoritmos de thresholding, o del valor umbral, permiten separar unaimagen en varias regiones. Concretamente, los de dos niveles permiten ex-traer el objeto y el fondo dada una imagen de entrada. En este apartadoanalizaremos tres de los algoritmos de thresholding de dos niveles que ofre-ce ImageJ por ser los que mejores resultados proporcionan en las imagenesbiomedicas estudiadas: el algoritmo de Huang, el IsoData, y el por defecto.

3.1 Algoritmo de Huang

Este metodo (ver [6]) se basa en la teorıa de conjuntos difusos para encontrarel valor umbral adecuado. A partir de un valor umbral, se define el grado depertenencia de un pıxel una de las dos regiones (objeto o fondo) como unafuncion inversamente proporcional a la diferencia entre el brillo del pıxel y elbrillo medio de la region. Lo deseable es que cada pıxel tenga el mayor gradode pertenencia a su region posible. Para ello se establece una medida para ladifusion de la imagen (existen varias alternativas) y se minimiza obteniendoası el valor umbral optimo.

3.1.1 Descripcion matematica

Sea X una imagen en escala de grises de tamano M × N con L niveles deluminosidad. Denotamos por xu,v ∈ [0, L) al nivel de luminosidad del pıxelsituado en la fila u y columna v. Ası, la imagen X es la matriz que contienelos niveles de luminosidad de sus pıxeles

X = {xuv}(u,v)∈[0,M)×[0,N)

25

Page 34: Análisis matemático de rutinas de procesamiento de imágenes

26 3.1. Algoritmo de Huang

Tambien daremos nombre a los niveles maximo y mınimo de luminosidadde una imagen

LM(X) = max(u,v)∈[0,M)×[0,N)

{xuv} (3.1)

Lm(X) = mın(u,v)∈[0,M)×[0,N)

{xuv} (3.2)

Sea hX el histograma de la imagen X definido como sigue

hX(t) = | {xuv ∈ X |xuv = t} | , t ∈ [0, L)

donde | · | denota el cardinal del conjunto.Dado un nivel de tolerancia t0 ∈ [0, L) llamaremos fondo de la imagen

a la region formada por aquellos pıxeles cuya luminosidad es menor o igualque el nivel de tolerancia t0 y objeto a la region formada por los pıxeles conmayor luminosidad. De esta forma los niveles medios de luminosidad para elfondo (µ0) y el objeto (µ1) son

µ0(X, t0) =

t0∑g=0

ghX(g)

/t0∑g=0

hX(g) (3.3)

µ1(X, t0) =L−1∑

g=t0+1

ghX(g)

/L−1∑

g=t0+1

hX(g) (3.4)

A partir de los elementos anteriores vamos a definir una funcion que midala relacion entre un pıxel y la region (fondo u objeto) a la que pertenece. Paraello, nos basaremos en la diferencia entre el nivel de luminosidad del pıxel yel de su region. Definimos la funcion tomando valores en [1

2, 1] como sigue

µX,t0(xuv) =

1

1 +|xuv − µ0|LM − Lm

, si xuv ≤ t0

1

1 +|xuv − µ1|LM − Lm

, si xuv > t0

(3.5)

Por ultimo, vamos a definir una medida de la borrosidad de una imagen.Existen varios enfoques, en ImageJ se usa la entropıa1 definida por De Luca

1El concepto de entropıa mide la cantidad de informacion que contiene una fuente deinformacion.

Page 35: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 3. Algoritmos de Thresholding 27

y Termini (ver [5]) como

E(X, t0) =1

n log 2

n∑i=1

S(µX,t0(xi)) (3.6)

donde {xi}i=1,..,n es el conjunto de pıxeles que forman la imagen (indexadosen cualquier orden) y S(x) es la funcion de Shannon

S(x) = −x log (x)− (1− x) log (1− x) (3.7)

Podemos reescribir (3.6) agrupando las sumas de los pıxeles con la mismaluminosidad usando el histograma hX

E(X, t0) =1

MN log 2

L−1∑g=0

S(µX,t0(g))hX(g) (3.8)

Una vez definidos estos conceptos, tomaremos como nivel de toleranciat0 ∈ [Lm, LM ] aquel que minimice la entropıa E(X, t0).

3.1.2 Analisis del algoritmo en ImageJ

El algoritmo para hallar dicho nivel de tolerancia es inmediato: basta conrecorrer todos los posibles t0 ∈ [Lm, LM ], y seleccionar aquel que proporcionela menor entropıa E(X, t0) para la imagen X sobre la que estamos traba-jando. El codigo para ello se encuentra en el fichero AutoThresholder.javaconcretamente en el metodo Huang(), y es el siguiente

Metodo Huang()

74 int Huang(int [] data ) {

81 int threshold =-1;

82 int ih , it;

83 int first_bin;

84 int last_bin;

85 double sum_pix;

86 double num_pix;

87 double term;

88 double ent;

89 double min_ent;

90 double mu_x;

93 first_bin =0;

94 for (ih = 0; ih < 256; ih++ ) {

95 if ( data[ih] != 0 ) {

Page 36: Análisis matemático de rutinas de procesamiento de imágenes

28 3.1. Algoritmo de Huang

96 first_bin = ih;

97 break;

98 }

99 }

102 last_bin =255;

103 for (ih = 255; ih >= first_bin; ih -- ) {

104 if ( data[ih] != 0 ) {

105 last_bin = ih;

106 break;

107 }

108 }

109 term = 1.0 / ( double ) ( last_bin - first_bin );

110 double [] mu_0 = new double [256];

111 sum_pix = num_pix = 0;

112 for ( ih = first_bin; ih < 256; ih++ ){

113 sum_pix += (double)ih * data[ih];

114 num_pix += data[ih];

115

116 mu_0[ih] = sum_pix / num_pix;

117 }

119 double [] mu_1 = new double [256];

120 sum_pix = num_pix = 0;

121 for ( ih = last_bin; ih > 0; ih -- ){

122 sum_pix += (double)ih * data[ih];

123 num_pix += data[ih];

124

125

126 mu_1[ih - 1] = sum_pix / ( double ) num_pix;

129 threshold = -1;

130 min_ent = Double.MAX_VALUE;

131 for ( it = 0; it < 256; it++ ){

132 ent = 0.0;

133 for ( ih = 0; ih <= it; ih++ ) {

134

135 mu_x = 1.0 / ( 1.0 + term * Math.abs ( ih - mu_0[it] ) );

136 if ( !(( mu_x < 1e-06 ) || ( mu_x > 0.999999))) {

137

138 ent += data[ih] * ( -mu_x * Math.log ( mu_x ) - ( 1.0 -

mu_x ) * Math.log ( 1.0 - mu_x ) );

139 }

140 }

142 for ( ih = it + 1; ih < 256; ih++ ) {

143

144 mu_x = 1.0 / ( 1.0 + term * Math.abs ( ih - mu_1[it] ) );

145 if ( !(( mu_x < 1e-06 ) || ( mu_x > 0.999999))) {

Page 37: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 3. Algoritmos de Thresholding 29

146

147 ent += data[ih] * ( -mu_x * Math.log ( mu_x ) - ( 1.0 -

mu_x ) * Math.log ( 1.0 - mu_x ) );

148 }

149 }

151 if ( ent < min_ent ) {

152 min_ent = ent;

153 threshold = it;

154 }

155 }

156 return threshold;

157 }

El algoritmo recibe como parametro de entrada el histograma de la ima-gen, y comienza realizando los calculos de las variables definidas en el apar-tado anterior: en las lıneas 75-91 se calculan LM , Lm segun (3.1), (3.2) y secontinua hallando los distintos µ0, µ1 para cada nivel de luminosidad segun(3.3) y (3.4) (lıneas 93-109).

El resto del metodo calcula, para cada t0 la entropıa de la siguiente manera

E∗(X, t0) =

t0∑g=0

S(µX,t0(g))h(g) +L−1∑g=t0

S(µX,t0(g))h(g) (3.9)

una formula similar a (3.8) donde se descarta el factor multiplicativo (ya queno hace diferencia a la hora de hallar la tolerancia que minimiza la entropıa)y separa la suma en dos terminos, esto es conveniente dada la definicion deµX,t0 . Concretamente, el calculo de µX,t0 se realiza en las lıneas 117 y 124y los terminos de la suma segun la formula (3.9) en las lıneas 119 y 126.Tambien se evitan los terminos tales que µX,t0 ≈ 1, ya que el calculo deS(µX,t0(xmn)) podrıa inducir errores numericos al incluir log (1− x) en laexpresion. Ademas estos terminos son irrelevantes ya que lım

x→1 S(x) = 0. Lomismo ocurre para µX,t0 ≈ 0.

Mejoras del algoritmo

Tal y como se describe en el artıculo original [6] a la hora de determinar elnivel de tolerancia que minimiza la entropıa no es necesario iterar sobre todoslos posibles niveles de brillo, basta con hacerlo sobre aquellos niveles presentesen la imagen. Ademas los niveles mınimo y maximo ya han sido calculados enel metodo, por lo que no supone ningun coste adicional hallar dichos valores.Por tanto basta que el bucle de la lınea 113 itere sobre [first bin, last bin] enlugar de [0, 256). Ası se reduce el tiempo de computo, en especial en imagenes

Page 38: Análisis matemático de rutinas de procesamiento de imágenes

30 3.2. IsoData y algoritmo de Threshold por defecto

con poco contraste. Tampoco son necesarias las comprobaciones de valorescercanos a 0 en las lıneas 118 y 125, ya que la funcion toma valores en [0,5, 1],como se ve claramente en su definicion en (3.5).

3.2 IsoData y algoritmo de Threshold por de-

fecto

Este algoritmo (basado en [7]) utiliza otro enfoque para encontrar el valorumbral adecuado, basandose en el histograma. La presencia de dos picosen el histograma de una imagen en escala de grises implica dos regionesdiferenciadas por su brillo en la imagen. Es razonable por tanto elegir comonivel umbral el valor medio entre esos dos picos.

3.2.1 Descripcion matematica

Siguiendo con las notaciones anteriores, sea X una imagen y xu,v ∈ X elnivel de luminosidad del pıxel situado en (u, v). Comenzamos seleccionandoun nivel de tolerancia inicial t0 = 1. A partir del nivel de tolerancia cal-culamos el nivel medio de luminosidad del fondo y del objeto, µ0(X, t0) yµ1(X, t0) usando el histograma de la imagen, como se vio en (3.3) y (3.4), y

establecemos un nuevo nivel de tolerancia tm =µ0 + µ1

2.

Si t0 = tm hemos terminado y el nivel de tolerancia es t0. En otro caso,tomamos t0 := tm y repetimos el procedimiento hasta alcanzar la igualdad2.

El algoritmo por defecto de ImageJ es este mismo metodo con una ligeramodificacion: antes de aplicar el metodo IsoData se modifica el histogramaligeramente. Sea hM el mayor valor del histograma, y hM2 el segundo mayorvalor del histograma. Si hM > 2 ∗ hM2 entonces hM := 1,5hM2. Tras estecambio, se aplica el algoritmo IsoData al nuevo histograma. Esta modificacionayuda a obtener valores umbral para imagenes cuyo histograma contienecambios abruptos en los niveles mas comunes.

3.2.2 Analisis del algoritmo en ImageJ

Comenzamos analizando la implementacion de IsoData en ImageJ:

Metodo IsoData

222 int IsoData(int[] data ) {

2Notar que el proceso siempre termina dado que µ0 ≤µ0 + µ1

2≤ µ1 y se usan numeros

enteros.

Page 39: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 3. Algoritmos de Thresholding 31

222 int i, l, totl , g=0;

223 double toth , h;

224 for (i = 1; i < 256; i++) {

225 if (data[i] > 0){

226 g = i + 1;

227 break;

228 }

229 }

230 while (true){

231 l = 0;

232 totl = 0;

233 for (i = 0; i < g; i++) {

234 totl = totl + data[i];

235 l = l + (data[i] * i);

236 }

237 h = 0;

238 toth = 0;

239 for (i = g + 1; i < 256; i++){

240 toth += data[i];

241 h += (( double)data[i]*i);

242 }

243 if (totl > 0 && toth > 0){

244 l /= totl;

245 h /= toth;

246 if (g == (int) Math.round((l + h) / 2.0))

247 break;

248 }

249 g++;

250 if (g > 254)

251 return -1;

252 }

253 return g;

254 }

Existen bastantes problemas con esta implementacion:

• En primer lugar, el algoritmo es poco eficiente, O(n2) siendo n el ta-mano del histograma; pudiendo ser implementado en O(n)3

• Notar que a las variables l y h se les aplica una logica y operacionessimilares, sin embargo una es declarada entera, y otra con precision decoma flotante. Ademas en los dos casos se comenten errores numericos;en la lınea 267 se usa aritmetica de coma flotante para acumular sumasde enteros mientras que en la lınea 270 se realiza una division enteracuando deberıa ser con decimales.

3La implementacion propuesta mas adelante es aproximadamente 10 veces mas rapidapara histogramas de este tamano (256 valores).

Page 40: Análisis matemático de rutinas de procesamiento de imágenes

32 3.2. IsoData y algoritmo de Threshold por defecto

• Se usa el tipo int para almacenar las sumas, por lo que es posible quese produzcan desbordamientos4.

• Ademas, el algoritmo no es equivalente al explicado en el artıculo enel que se basan [7], ya que en lugar de usar como nueva tolerancia lamedia de las dos calculadas, se toma el siguiente valor a la toleranciaantigua.

Veamos ahora como se implementa la modificacion del IsoData (algoritmopor defecto en ImageJ).

Metodo defaultIsoData

282 int defaultIsoData(int[] data) {

284 int n = data.length;

285 int[] data2 = new int[n];

286 int mode=0, maxCount =0;

287 for (int i=0; i<n; i++) {

288 int count = data[i];

289 data2[i] = data[i];

290 if (data2[i]>maxCount) {

291 maxCount = data2[i];

292 mode = i;

293 }

294 }

295 int maxCount2 = 0;

296 for (int i = 0; i<n; i++) {

297 if ((data2[i]>maxCount2) && (i!=mode))

298 maxCount2 = data2[i];

299 }

300 int hmax = maxCount;

301 if ((hmax >( maxCount2 *2)) && (maxCount2 !=0)) {

302 hmax = (int)(maxCount2 * 1.5);

303 data2[mode] = hmax;

304 }

305 return IJIsoData(data2);

306 }

Notemos que se recorre dos veces el histograma sin ser necesario y tambiense hace una copia del histograma original antes de modificarlo, cuando, te-niendo en cuenta que solo se modifica un valor del mismo, podrıa restaurarsey evitar la copia.

4Bastarıa una imagen bastante oscura con dimensiones 3000× 3000, ya que√Integer.MAX VALUE

255≈ 2900

Page 41: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 3. Algoritmos de Thresholding 33

Mejoras del algoritmo

Se proponen las siguientes implementaciones para los algoritmos IsoData(equivalente eliminando los tres primeros problemas expuestos) y Default(equivalente eliminando la copia innecesaria y con un solo recorrido).

Metodo propuesto como mejora para IsoData

1 public static int IsoDataFix(int[] data) {

2 int nAboveG = 0;

3 long totalAboveG = 0;

4 int nBelowG = 0;

5 long totalBelowG = 0;

6 int first = 256;

7

8 for (int i = 255; i >= 0; i--) {

9 nAboveG += data[i];

10 totalAboveG += i*data[i];

11 if (data[i] > 0) {

12 first = i;

13 }

14 }

15

16 for (int g=first; g <256; g++) {

17 nBelowG += data[g];

18 nAboveG -= data[g];

19

20 totalBelowG += g*data[g];

21 totalAboveG -= g*data[g];

22

23 double belowGMean = totalBelowG / (double) nBelowG;

24 double aboveGMean = totalAboveG / (double) nAboveG;

25

26 if (g == (int) StrictMath.round(( belowGMean + aboveGMean) /

2.0f))

27 return g;

28 }

29 return -1;

30 }

Metodo propuesto como mejora para Default

1 public static int defaultIsoDataFix(int[] data) {

2 int maxIndex = -1;

3 int maxValue = -1;

4 int maxValue2 = -1;

5

6 for (int i=0; i<data.length; i++) {

Page 42: Análisis matemático de rutinas de procesamiento de imágenes

34 3.3. Aplicaciones teoricas

7 if (data[i] > maxValue2) {

8 if (data[i] > maxValue) {

9 maxValue2 = maxValue;

10 maxValue = data[i];

11 maxIndex = i;

12 } else {

13 maxValue2 = data[i];

14 }

15 }

16 }

17

18 int oldValue = data[maxIndex ];

19

20 if (maxValue > 2 * maxValue2) {

21 data[maxIndex] = (int) (1.5 * maxValue2);

22 }

23

24 int retValue = IJIsoData(data);

25 data[maxIndex] = oldValue;

26

27 return retValue;

28 }

3.3 Aplicaciones teoricas

Los algoritmos de thresholding permiten extraer la informacion relevante deuna imagen de entrada (objeto) y separarla de la otra region que no contieneinformacion relevante (fondo). Es un paso necesario en muchos procesos querequieren identificar formas o patrones en imagenes: reconocimiento de textotanto a mano como a maquina, extraccion de logotipos, contenido grafico,partituras musicales, procesamiento de mapas para encontrar lıneas, leyen-das, o textos; inspeccion de la calidad de materiales, etc.

3.4 Aplicaciones al tratamiento de imagenes

biomedicas

Como ya se ha dicho, esta es una tecnica utilizada para dividir una imagen endistintas regiones. En el estudio de imagenes biomedicas, son especialmenteutilizados los algoritmos de thresholding de dos niveles, ya que es necesariodistinguir los objetos de estudio del fondo de la imagen. Para ello, es necesa-rio marcar o etiquetar los pıxeles de la imagen, de manera que se identifiquea que region pertenecen. En el Grupo de Informatica, y en general en este

Page 43: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 3. Algoritmos de Thresholding 35

tipo de estudios o investigaciones basadas en la informacion que contienen lasimagenes, esta tecnica es comunmente usada en el procesamiento de image-nes como paso previo a un estudio posterior sobre las diferentes regiones. Enconcreto, el algoritmo de Huang y el IsoData (default) se usan en los pluginsdesarrollados por el Grupo de Informatica, NeuronZigZagJ y NucleusJ res-pectivamente [2].

Resultados de la binarizacion de una imagen no preprocesada (izquierda) y de una imagena la que se le ha aplicado el filtro de Gauss con σ = 2 (derecha) y posteriormente elalgoritmo de Huang.

Page 44: Análisis matemático de rutinas de procesamiento de imágenes
Page 45: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 4

Algoritmo FindMaxima

Este algoritmo permite encontrar los maximos locales en una imagen de uncanal. Para imagenes de varios canales, se encuentran los maximos de lumi-nosidad, obtenida a su vez mediando los valores de los distintos canales. Sinembargo, habitualmente no resulta util encontrar todos los maximos localesdebido al ruido existente en la imagen, por lo que se establece un nivel detolerancia al ruido. No se ha encontrado una explicacion detallada de estealgoritmo, por lo que esta descripcion se ha extraıdo a partir de un analisisdel codigo.

Para cada maximo local se toma la region de pıxeles conexos1 con dichomaximo local cuyo valor difiere del maximo en una cantidad menor o iguala la tolerancia (notar que una region puede contener mas de un maximolocal). Por ultimo para cada region se toma como maximo el maximo localque este mas cercano al baricentro de los maximos globales de dicha region.

Existen varias opciones para el algoritmo que permiten elegir entre dis-tintos formatos para la salida de los datos, segun los intereses del usuario:

• Single Points Crea una imagen binaria donde se marcan todos los

1Aunque es posible definir una topologıa adecuada sobre la imagen que induzca laconexion deseada, es suficiente y mas sencillo definir adyacencia entre pıxeles y conexionen funcion de las coordenadas. Esta se denomina 8-adyacencia y es la definida en el grafosubyacente.

Definicion. Dos pıxeles (x0, y0), (x1, y1) se dicen adyacentes si

|x0 − x1| ≤ 1 ∧ |y0 − y1| ≤ 1

Definicion. Un subconjunto R de una imagen se dice conexo si para cada x, y ∈ R existeuna sucesion x = x0, x1, x2, ..., xn = y tal que xi, xi+1 son adyacentes ∀i = 0, ..., n − 1 yxi ∈ R ∀i = 0, ..., n

37

Page 46: Análisis matemático de rutinas de procesamiento de imágenes

38 4.1. Analisis del algoritmo en ImageJ

maximos locales.

• Maxima Within Tolerance: Crea una imagen binaria donde se mar-can todos los maximos locales y sus regiones.

• Segmented Particles: A partir de los maximos locales, divide la ima-gen en regiones utilizando el algoritmo de transformacion divisoria2

(wathershed).

• Point Selection: Selecciona los maximos locales en la imagen actual.

• List: Presenta una tabla con las coordenadas de cada maximo local.

• Count: Calcula el numero de maximos locales.

El algoritmo se puede aplicar a una imagen completa o a una regionde la imagen, excepto para el modo Segmented Particles, que solo se puedeaplicar a una imagen completa. Tambien es necesario especificar los siguientesparametros:

• Tolerancia al ruido: Valor entero tal que solo se consideraran losmaximos cuya diferencia con los pıxeles adyacentes sea mayor o iguala dicho valor. A mayor valor, menor numero de maximos encontrados.

• Excluir maximos en los bordes: Si se selecciona esta opcion, no seconsideraran los maximos cuya region sea adyacente a un borde de laimagen.

• Fondo claro: Debe ser seleccionada si el fondo de la imagen es masbrillante que los objetos que se buscan. A efectos practicos, invierte elvalor de los pıxeles antes de aplicar el algoritmo.

4.1 Analisis del algoritmo en ImageJ

El algoritmo sigue el siguiente esquema:

1. Se localizan los maximos locales.

2. Se ordenan en orden descendente.

2No se estudiara aquı en detalle, pero se puede consultar la documentacion de ImageJ.

Page 47: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 4. Algoritmo FindMaxima 39

3. Para cada maximo local, se realiza un algoritmo de llenado3. Si desdeun maximo se llena una zona ya llenada por un maximo anterior, elmaximo actual es descartado4.

Se implementa en la clase MaximumFinder, comenzando en el metodorun() por tratar la ROI de la imagen (lıneas 188-196), se guarda la ROI si seha seleccionado el modo Point Selection (ya que esto modifica la ROI actual),y se elimina si el modo seleccionado es Segmented Particles (que como ya se hacomentado, solo se puede aplicar a imagenes completas). Despues se inviertela imagen si fuera necesario (imagenes que no esten invertidas y con fondoclaro) respetando la calibracion (lıneas 199-212). Tras este tratamiento inicialde la imagen, se invoca al metodo findMaxima() (lınea 214) que aplicara elalgoritmo propiamente dicho (las lıneas finales 215-233 presentan el resultadodel algoritmo por pantalla).

Metodo run (punto de entrada del plugin)

187 public void run(ImageProcessor ip) {

188 Roi roi = imp.getRoi ();

189 if (outputType == POINT_SELECTION && !roiSaved) {

190 imp.saveRoi ();

191 roiSaved = true;

192 }

193 if (roi!=null && (!roi.isArea () || outputType ==

SEGMENTED)) {

194 imp.deleteRoi ();

195 roi = null;

196 }

197 boolean invertedLut = imp.isInvertedLut ();

198 double threshold = useMinThreshold?ip.getMinThreshold

():ImageProcessor.NO_THRESHOLD;

199 if (( invertedLut &&! lightBackground) || (! invertedLut

&& lightBackground)) {

200 threshold = ImageProcessor.NO_THRESHOLD;

201 float [] cTable = ip.getCalibrationTable ();

202 ip = ip.duplicate ();

203 if (cTable ==null) {

204 ip.invert ();

205 } else {

206 float [] invertedCTable = new float[cTable.

length ];

3Este algoritmo consiste en recorrer los pıxeles adyacentes al maximo local y luegorecursivamente los adyacentes a estos para determinar la region asociada al maximo local(teniendo en cuenta la tolerancia al ruido establecida). Se analizara en detalle mas adelante,durante el analisis del metodo analyzeAndMarkMaxima()

4Se asignara un maximo a cada region, segun lo establecido en la introduccion al algo-ritmo.

Page 48: Análisis matemático de rutinas de procesamiento de imágenes

40 4.1. Analisis del algoritmo en ImageJ

207 for (int i=cTable.length -1; i>=0; i--)

208 invertedCTable[i] = -cTable[i];

209 ip.setCalibrationTable(invertedCTable);

210 }

211 ip.setRoi(roi);

212 }

213 ByteProcessor outIp = null;

214 outIp = findMaxima(ip, tolerance , threshold ,

outputType , excludeOnEdges , false);

215 if (outIp == null) return;

216 if (! Prefs.blackBackground)

217 outIp.invertLut ();

218 String resultName;

219 if (outputType == SEGMENTED)

220 resultName = " Segmented";

221 else

222 resultName = " Maxima";

223 String outname = imp.getTitle ();

224 if (imp.getNSlices () >1)

225 outname += "("+imp.getCurrentSlice ()+")";

226 outname += resultName;

227 if (WindowManager.getImage(outname)!=null)

228 outname = WindowManager.getUniqueName(outname);

229 ImagePlus maxImp = new ImagePlus(outname , outIp);

230 Calibration cal = imp.getCalibration ().copy();

231 cal.disableDensityCalibration ();

232 maxImp.setCalibration(cal);

233 maxImp.show();

234 }

En el metodo findMaxima() se lleva a cabo el procesamiento de la imagen.En primer lugar se adapta el threshold en caso de estar usando imagenescalibradas 5 y se crea una plantilla del mismo tamano que la imagen dondese iran marcando los maximos y sus regiones (lıneas 364-369). Seguidamentese calculan el maximo y el mınimo global de la imagen (lıneas 371-379).

Metodo findMaxima

361 public ByteProcessor findMaxima(ImageProcessor ip , double

tolerance , double threshold ,

362 int outputType , boolean excludeOnEdges , boolean

isEDM) {

363 if (dirOffset == null) makeDirectionOffsets(ip);

364 Rectangle roi = ip.getRoi ();

365 byte[] mask = ip.getMaskArray ();

5Una imagen calibrada es aquella que tiene establecido un threshold o umbral de formaque solo se consideran los pıxeles con brillo superior a dicho valor.

Page 49: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 4. Algoritmo FindMaxima 41

366 if (threshold != ImageProcessor.NO_THRESHOLD && ip.

getCalibrationTable ()!=null &&

367 threshold >0 && threshold <ip.

getCalibrationTable ().length)

368 threshold = ip.getCalibrationTable ()[(int)

threshold ];

369 ByteProcessor typeP = new ByteProcessor(width , height

);

370 byte[] types = (byte []) typeP.getPixels ();

371 float globalMin = Float.MAX_VALUE;

372 float globalMax = -Float.MAX_VALUE;

373 for (int y=roi.y; y<roi.y+roi.height; y++) {

374 for (int x=roi.x; x<roi.x+roi.width; x++) {

375 float v = ip.getPixelValue(x, y);

376 if (globalMin >v) globalMin = v;

377 if (globalMax <v) globalMax = v;

378 }

379 }

380 if (threshold != ImageProcessor.NO_THRESHOLD)

381 threshold -= (globalMax -globalMin)*1e-6;

382

383 boolean excludeEdgesNow = excludeOnEdges &&

outputType != SEGMENTED;

384

385

386

387 long[] maxPoints = getSortedMaxPoints(ip , typeP ,

excludeEdgesNow , isEDM , globalMin , globalMax ,

threshold);

388

389

390 float maxSortingError = 0;

391 if (ip instanceof FloatProcessor)

392 maxSortingError = 1.1f * (isEDM ? SQRT2 /2f : (

globalMax -globalMin)/2e9f);

393 analyzeAndMarkMaxima(ip , typeP , maxPoints ,

excludeEdgesNow , isEDM , globalMin , tolerance ,

outputType , maxSortingError);

394

395 if (outputType == POINT_SELECTION || outputType ==LIST

|| outputType == COUNT)

396 return null;

397

398 ByteProcessor outIp;

399 byte[] pixels;

400 if (outputType == SEGMENTED) {

401

402

Page 50: Análisis matemático de rutinas de procesamiento de imágenes

42 4.1. Analisis del algoritmo en ImageJ

403 outIp = make8bit(ip, typeP , isEDM , globalMin ,

globalMax , threshold);

404

405 cleanupMaxima(outIp , typeP , maxPoints);

406

407

408 if (! watershedSegment(outIp))

409 return null;

410 if (! isEDM) cleanupExtraLines(outIp);

411 watershedPostProcess(outIp);

412 if (excludeOnEdges) deleteEdgeParticles(outIp ,

typeP);

413 } else {

414 for (int i=0; i<width*height; i++)

415 types[i] = (byte)((( types[i]& outputTypeMasks[

outputType ])!=0) ?255:0);

416 outIp = typeP;

417 }

418 byte[] outPixels = (byte []) outIp.getPixels ();

419

420 if (roi!=null) {

421 for (int y=0, i=0; y<outIp.getHeight (); y++) {

422 for (int x=0; x<outIp.getWidth (); x++, i++) {

423 if (x<roi.x || x>=roi.x+roi.width || y<

roi.y || y>=roi.y+roi.height)

outPixels[i] = (byte)0;

424 else if (mask !=null && (mask[x-roi.x +

roi.width*(y-roi.y)]==0)) outPixels[i]

= (byte)0;

425 }

426 }

427 }

428

429 return outIp;

430 }

En las lıneas 380, 381 y 390-392 se establecen valores adecuados paralas variables threshold y maxSortingError, necesarias para lidiar con posi-bles errores numericos. Comentaremos mas adelante por que son necesariasestas variables y su uso (lo haremos brevemente, ya que no afecta al tipode imagenes en las que estamos interesados). Para llevar a cabo el procesa-miento de la imagen, el algoritmo se apoya en dos metodos encargados derealizar los pasos mencionados al principio de este apartado: getSortedMax-Points() (lınea 387) se encarga de obtener los maximos locales ordenados, yanalyzeAndMarkMaxima() (lınea 393) es responsable de aplicar el algoritmode llenado y marcar los maximos validos y sus regiones en la plantilla typeP.

Page 51: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 4. Algoritmo FindMaxima 43

Por ultimo, se preparan los resultados para la salida (lıneas 400-417). Siesta usando el modo SEGMENTED, se usan una serie de metodos auxilia-res ya que el postprocesamiento es mas complejo (no se estudiara aquı endetalle). En otro caso, se marcan en la plantilla solo los pıxeles que el mo-do actual requiere (lıneas 413-418), usando la variable outputTypeMask, quedefine que pıxeles marcar en funcion del modo del algoritmo que se este usan-do, junto a los valores enteros asignados a las variables que representan losdistintos modos: SINGLE POINTS = 0, IN TOLERANCE = 1, SEGMEN-TED = 2 (lıneas 48-58). Tambien se borran los pıxeles marcados fuera de laregion de interes en la plantilla (lıneas 420-427). Pasamos ahora a estudiarlas dos funciones mencionadas en las que se basa findMaxima().

Declaracion de la variable outputTypeMask

101 byte[] outputTypeMasks = new byte[] {MAX_POINT , MAX_AREA ,

MAX_AREA };

4.1.1 Obtencion de los maximos locales

El metodo getSortedMaxPoints() es el encargado de realizar los primerospasos (localizacion y ordenacion de los maximos locales) usando el siguientecodigo:

Metodo getSortedMaxima()

444 long[] getSortedMaxPoints(ImageProcessor ip ,

ByteProcessor typeP , boolean excludeEdgesNow ,

445 boolean isEDM , float globalMin , float globalMax ,

double threshold) {

446 Rectangle roi = ip.getRoi ();

447 byte[] types = (byte []) typeP.getPixels ();

448 int nMax = 0;

449 boolean checkThreshold = threshold != ImageProcessor.

NO_THRESHOLD;

450

451

452 for (int y=roi.y; y<roi.y+roi.height; y++) {

453

454 for (int x=roi.x, i=x+y*width; x<roi.x+roi.width;

x++, i++) {

455 float v = ip.getPixelValue(x,y);

456

457 if (v== globalMin) continue;

458 if (excludeEdgesNow && (x==0 || x==width -1 ||

y==0 || y==height -1)) continue;

459 if (checkThreshold && v<threshold) continue;

Page 52: Análisis matemático de rutinas de procesamiento de imágenes

44 4.1. Analisis del algoritmo en ImageJ

460 boolean isMax = true;

461

462 boolean isInner = (y!=0 && y!=height -1) && (x

!=0 && x!=width -1);

463 for (int d=0; d<8; d++) {

464 if (isInner || isWithin(x, y, d)) {

465 float vNeighbor = ip.getPixelValue(x+

DIR_X_OFFSET[d], y+DIR_Y_OFFSET[d

]);

466

467 if (vNeighbor > v) {

468 isMax = false;

469 break;

470 }

471 }

472 }

473 if (isMax) {

474 types[i] = MAXIMUM;

475 nMax ++;

476 }

477 }

478 }

479

480

481

482 float vFactor = (float)(2e9/(globalMax -globalMin));

483 long[] maxPoints = new long[nMax];

484 int iMax = 0;

485 for (int y=roi.y; y<roi.y+roi.height; y++)

486 for (int x=roi.x, p=x+y*width; x<roi.x+roi.width;

x++, p++)

487 if (types[p]== MAXIMUM) {

488 float fValue = ip.getPixelValue(x,y);

489 int iValue = (int)((fValue -globalMin)*

vFactor);

490 maxPoints[iMax ++] = (long)iValue <<32|p;

491 }

492

493

494 Arrays.sort(maxPoints);

495

496 return maxPoints;

497 }

El primer bucle (lıneas 452-480) recorre la region de interes de la imagenanotando los maximos locales en la plantilla typeP (lıneas 475-478). Paraello simplemente comprueba todos los pıxeles adyacentes a cada pıxel de laregion (lıneas 465-474). Notar que solo se tienen en cuenta los maximos que

Page 53: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 4. Algoritmo FindMaxima 45

no estan los bordes si el parametro excludeEdgesNow no es true (lınea 458),tambien se tiene en cuenta el threshold de la imagen.

Despues se genera un array de longs (64 bits) que contiene los maxi-mos locales del siguiente modo: en los 32 bits de mayor peso el valor delmaximo convertido a un entero (conservando el orden)6, en los 32 bits eldesplazamiento del maximo. Notar que esta forma de empaquetar el valor ylas coordenadas de cada maximo en un long, mantiene el orden (es decir, ellong asociado a un maximo sera mayor que el long asociado a un segundomaximo si y solo si el valor del primer maximo es mayor que el valor delsegundo)7.

Por ultimo se ordena dicho array y se devuelve.

4.1.2 Analisis de los maximos y algoritmo de llenado

Una vez obtenida la lista de maximos locales ordenada, hay que aplicar elalgoritmo de llenado a cada uno de ellos, recorriendolos descendientemente.Esta tarea es llevada a cabo por el metodo analyzeAndMarkMaxima().

Para ello, se itera sobre la lista (ordenada ascendientemente) desde elfinal hacia el inicio (lınea 529). Las siguientes lıneas recogen en variableslocales la informacion sobre el maximo local sobre el que se esta actuando:el desplazamiento que esta almacenado en los 32 bits de menor peso sonobtenidos casteando del tipo long al tipo int (lınea 531) y a partir de estey de la propia imagen se obtienen las coordenadas del maximo (x0,y0 ) y suvalor, v0 (lıneas 536-538). Como veremos mas adelante, aunque se recorre

6 Concretamente, como se observa en las lıneas 484 y 491, se usa la siguiente aplicacion:

[globalMin, globalMax] ⊂ Float→ [0, 2× 109] ⊂ Int

fV alue 7→ (fV alue− globalMin)2× 109

globalMax− globalMin

que es la biyeccion natural entre dos intervalos. Notar que, debido a errores numericos, laaplicacion anterior podrıa no ser inyectiva. Una mejor eleccion para este fin es la aplicacion

Idbits : Float*→ D ⊂ Int

donde Idbits es la aplicacion que deja fija la expresion en bits, Float* es el conjunto delos numeros de coma flotante normalizados (es decir, excluimos NaNs, ±∞ y numerosdesnormalizados) y D = Idbits(Float*) es algun subconjunto del rango de numeros enteros.Es inmediato que esta aplicacion es una biyeccion y se puede ver que conserva el orden.Java proporciona los metodos estaticos Float.floatToRawIntBits y Float.intBitsToFloatque permitirıan implementar esta biyeccion.

7Notar que, en otros lenguajes, esto podrıa no ser ası ya que se esta asumiendo que losenteros se representan en complemento a dos y que los tamanos de int y long son 32 y 64bits, respectivamente. Java sı garantiza dichas asunciones.

Page 54: Análisis matemático de rutinas de procesamiento de imágenes

46 4.1. Analisis del algoritmo en ImageJ

la lista de maximos locales visitando cada uno una vez, existe la posibilidadde que, al aplicar el algoritmo a un maximo, se encuentren otros, de ahı lacomprobacion de la lınea 533 para asegurar que el maximo que se va a tratarno ha sido tratado ya.

Metodo analyzeAndMarkMaxima, recorrido de os maximos)

515 void analyzeAndMarkMaxima(ImageProcessor ip , ByteProcessor

typeP , long[] maxPoints , boolean excludeEdgesNow ,

516 boolean isEDM , float globalMin , double tolerance , int

outputType , float maxSortingError) {

517 byte[] types = (byte []) typeP.getPixels ();

518

519 int nMax = maxPoints.length;

520 int [] pList = new int[width*height ];

521 Vector xyVector = null;

522 Roi roi = null;

523 boolean displayOrCount = outputType == POINT_SELECTION

|| outputType ==LIST|| outputType == COUNT;

524 if (displayOrCount)

525 xyVector=new Vector ();

526 if (imp!=null)

527 roi = imp.getRoi ();

528

529 for (int iMax=nMax -1; iMax >=0; iMax --) {

530

531 int offset0 = (int)maxPoints[iMax];

532

533 if ((types[offset0 ]& PROCESSED)!=0)

534 continue;

Antes de comenzar con el algoritmo de llenado sobre el maximo local en elque nos hemos situado, se inicializa la representacion de la lista de pıxeles enla region que llena el maximo local actual y se introduce un do-while que seencargara de repetir el algoritmo si se encuentra un error8 en el orden de losmaximos locales (controlado por la variable sortingError que se compruebaen la lınea 641). Tambien se inicializan las variables xEqual, yEqual y nEqualque se usaran para mediar las coordenadas de todos los pıxeles iguales almaximo local en la region de llenado para determinar el punto unico que seasignara a la region.

Metodo analyzeAndMarkMaxima, comienzo del algoritmo de llenado)

535

8Debido a que el metodo getSortedMaxima() utiliza comparaciones con precision de 32bits (int), se podrıan dar errores numericos para ciertas imagenes. Sin embargo, no se danerrores numericos para las imagenes que estamos estudiando (de 8 bits).

Page 55: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 4. Algoritmo FindMaxima 47

536 int x0 = offset0 % width;

537 int y0 = offset0 / width;

538 float v0 = ip.getPixelValue(x0,y0);

539 boolean sortingError;

540 do {

541 pList [0] = offset0;

542 types[offset0] |= (EQUAL|LISTED);

543 int listLen = 1;

544 int listI = 0;

545 boolean isEdgeMaximum = (x0==0 || x0==width -1 || y0

==0 || y0==height -1);

546 sortingError = false;

547 boolean maxPossible = true;

548 double xEqual = x0;

549 double yEqual = y0;

550 int nEqual = 1;

Seguidamente se recorre la lista de pıxeles en la region asociada al maximo(que en la primera iteracion solo contiene el propio maximo) con la expresiondo-while de la lınea 551 y para cada uno de sus elementos, se recorren sus 8pıxeles adyacentes (for lınea 557). Tras realizar comprobaciones basicas (elpıxel esta dentro de los lımites de la imagen y aun no se ha iterado sobreel) se asegura que el pıxel no esta marcado como un maximo; si lo fuera, elmaximo cuya region estamos iterando ya no puede serlo (lıneas 561-565).

Metodo analyzeAndMarkMaxima, algoritmo de llenado

551 do {

552 int offset = pList[listI];

553 int x = offset % width;

554 int y = offset / width;

555

556 boolean isInner = (y!=0 && y!=height -1) && (x!=0

&& x!=width -1);

557 for (int d=0; d<8; d++) {

558 int offset2 = offset+dirOffset[d];

559 if (( isInner || isWithin(x, y, d)) && (types[

offset2 ]& LISTED)==0) {

560

561 if (( types[offset2 ]& PROCESSED)!=0) {

562 maxPossible = false;

563

564 break;

565 }

Llegados a este punto se tiene que determinar si el pıxel actual (x2,y2 )con valor v2 (que es uno de los adyacentes a (x,y) que a su vez es uno

Page 56: Análisis matemático de rutinas de procesamiento de imágenes

48 4.1. Analisis del algoritmo en ImageJ

de los que pertenece a la region del maximo local (x0,y0 ) sobre los que seesta iterando) pertenece o no la region de llenado del maximo local (x0,y0 )con valor v0. Para ello se realizan dos comprobaciones en las lıneas 569 y573. La primera de ellas comprueba fallos numericos que pueden ocurriren imagenes de 32 bits representadas por FloatProcessors. En la segundacondicion se comprueba si el nuevo pıxel corresponde a la region del maximolocal, es decir, si su diferencia es menor que la tolerancia. Si es ası, se anade ala lista y lo marcamos como listado (lıneas 582-584), ademas si el pıxel actual(x2,y2 ) es mayor que el maximo local (x0,y0 ), se cambia el maximo local alpıxel actual (lıneas 574-581). Si es igual, se marca como tal y se actualizanlas variables xEqual, yEqual, nEqual que mas tarde se utilizaran para mediarlas coordenadas de todos los pıxeles iguales al maximo local en la region paraasignarle un punto si la salida es SINGLE POINTS.

Metodo analyzeAndMarkMaxima, ampliacion de la region asociada a unmaximo

566 int x2 = x+DIR_X_OFFSET[d];

567 int y2 = y+DIR_Y_OFFSET[d];

568 float v2 = ip.getPixelValue(x2, y2);

569 if (v2 > v0 + maxSortingError) {

570 maxPossible = false;

571

572 break;

573 } else if (v2 >= v0 -( float)tolerance) {

574 if (v2 > v0) {

575 sortingError = true;

576 offset0 = offset2;

577 v0 = v2;

578 x0 = x2;

579 y0 = y2;

580

581 }

582 pList[listLen] = offset2;

583 listLen ++;

584 types[offset2] |= LISTED;

585 if (x2==0 || x2==width -1 || y2==0 || y2==

height -1) {

586 isEdgeMaximum = true;

587 if (excludeEdgesNow) {

588 maxPossible = false;

589 break;

590 }

591 }

592 if (v2==v0) {

593 types[offset2] |= EQUAL;

594 xEqual += x2;

Page 57: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 4. Algoritmo FindMaxima 49

595 yEqual += y2;

596 nEqual ++;

597 }

598 }

599 }

600 }

601 listI ++;

602 } while (listI < listLen);

Este procedimiento continua hasta que no hay mas pıxeles en la region,seguidamente se comprueba que no han ocurrido errores de ordenacion (sihubieran ocurrido, se repite el algoritmo) y se calcula el maximo correspon-diente a la region: el pıxel de igual intensidad al maximo local mas cercanoal baricentro9 de los pıxeles de igual intensidad al maximo local. Tambiense marcan los pıxeles de la region con el atributo LISTED y, si no hay unmaximo posible para esta region (por ejemplo, por ser una region del borde ytener activa la opcion excluir maximos en los bordes) tambien como EQUAL(es decir, si no hay maximo, se entendera que todos los pıxeles son igualesal maximo). Por ultimo, se marca el punto como maximo y, si el metodo desalida seleccionado lo requiere, se anade a la lista de maximos.

Metodo analyzeAndMarkMaxima, marcaje de los puntos en la plantilla

603

604 if (sortingError) {

605 for (listI =0; listI <listLen; listI ++)

606 types[pList[listI ]] = 0;

607 } else {

608 int resetMask = ~( maxPossible?LISTED :( LISTED|EQUAL));

609 xEqual /= nEqual;

610 yEqual /= nEqual;

611 double minDist2 = 1e20;

612 int nearestI = 0;

613 for (listI =0; listI <listLen; listI ++) {

614 int offset = pList[listI];

615 int x = offset % width;

616 int y = offset / width;

617 types[offset] &= resetMask;

618 types[offset] |= PROCESSED;

619 if (maxPossible) {

9Sea X = {(xi, yi) | i ∈ I} (donde I es una familia finita de ındices) un conjunto depuntos, su baricentro es el punto

(xb, yb) =1

|I|∑i∈I

(xi, yi)

Page 58: Análisis matemático de rutinas de procesamiento de imágenes

50 4.1. Analisis del algoritmo en ImageJ

620 types[offset] |= MAX_AREA;

621 if ((types[offset ]&EQUAL)!=0) {

622 double dist2 = (xEqual -x)*( double)(xEqual -x) + (

yEqual -y)*( double)(yEqual -y);

623 if (dist2 < minDist2) {

624 minDist2 = dist2;

625 nearestI = listI;

626 }

627 }

628 }

629 }

630 if (maxPossible) {

631 int offset = pList[nearestI ];

632 types[offset] |= MAX_POINT;

633 if (displayOrCount && !(this.excludeOnEdges &&

isEdgeMaximum)) {

634 int x = offset % width;

635 int y = offset / width;

636 if (roi==null || roi.contains(x, y))

637 xyVector.addElement(new int[] {x, y});

638 }

639 }

640 }

641 } while (sortingError);

642 }

Con esto termina el algoritmo principal y quedan marcados todos losmaximos y sus regiones en la plantilla typeP. Las ultimas lıneas del metodo(645-697) preparan la salida de los datos para los formatos LIST, COUNT yPOINT SELECTION, utilizando la lista de las coordenadas de los maximosalmacenados en xyVector, recopilados durante la ejecucion del algoritmo.

Metodo analyzeAndMarkMaxima, datos de salida

645 if (displayOrCount && xyVector !=null) {

646 int npoints = xyVector.size();

647 if (outputType == POINT_SELECTION && npoints >0) {

648 int[] xpoints = new int[npoints ];

649 int[] ypoints = new int[npoints ];

650 for (int i=0; i<npoints; i++) {

651 int[] xy = (int []) xyVector.elementAt(i);

652 xpoints[i] = xy[0];

653 ypoints[i] = xy[1];

654 }

655 if (imp!=null) {

656 Roi points = new PointRoi(xpoints , ypoints ,

npoints);

657 (( PointRoi)points).setHideLabels(true);

658 imp.setRoi(points);

Page 59: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 4. Algoritmo FindMaxima 51

659 }

660 points = new Polygon(xpoints , ypoints ,

npoints);

661 } else if (outputType ==LIST) {

662 Analyzer.resetCounter ();

663 ResultsTable rt = ResultsTable.

getResultsTable ();

664 for (int i=0; i<npoints; i++) {

665 int[] xy = (int []) xyVector.elementAt(i);

666 rt.incrementCounter ();

667 rt.addValue("X", xy[0]);

668 rt.addValue("Y", xy[1]);

669 }

670 rt.show("Results");

671 } else if (outputType ==COUNT) {

672 ResultsTable rt = ResultsTable.

getResultsTable ();

673 rt.incrementCounter ();

674 rt.setValue("Count", rt.getCounter () -1,

npoints);

675 int measurements = Analyzer.getMeasurements ()

;

676 if (( measurements&Measurements.LABELS)!=0) {

677 String s = imp.getTitle ();

678 String roiName = roi!=null?roi.getName ():

null;

679 if (roiName !=null)

680 s += ":"+roiName;

681 if (imp.getStackSize () >1) {

682 ImageStack stack = imp.getStack ();

683 int currentSlice = imp.

getCurrentSlice ();

684 String label = stack.

getShortSliceLabel(currentSlice);

685 String colon = s.equals("")?"":":";

686 if (label!=null && !label.equals(""))

687 s += colon+label;

688 else

689 s += colon+currentSlice;

690 }

691 rt.setLabel(s, rt.getCounter () -1);

692 }

693 rt.show("Results");

694 }

695 }

696 if (previewing)

697 messageArea.setText (( xyVector ==null ? 0 :

xyVector.size())+" Maxima");

698 }

Page 60: Análisis matemático de rutinas de procesamiento de imágenes

52 4.2. Aplicaciones teoricas

4.2 Aplicaciones teoricas

Se aplica en situaciones en las que se desea encontrar regiones en una imagencon una intensidad uniforme y elevada respecto al resto de la imagen. Al-gunos ejemplos incluyen localizar celulas en imagenes biomedicas, estrellas ogalaxias en imagenes astronomicas o, en general, cualquier elemento que des-taque por su brillo en la imagen. En el caso de imagenes en blanco y negro,esto equivale a determinar las componentes conexas en la figura; este es elmodo en que es utilizado en las aplicaciones que presentamos a continuacion.

4.3 Aplicaciones al tratamiento de imagenes

biomedicas

En el caso de imagenes binarizadas (compuestas por pıxeles cuya intensidades la maxima o la mınima), este algoritmo encuentra las componentes co-nexas de la imagen, ya que tras encontrar algun maximo en cada region, elalgoritmo de llenado que hemos visto extiende cada region hasta llenar lacomponente conexa de dicho maximo, con independencia del nivel de tole-rancia.

Recuento de componentes conexas en una imagen binarizada utilizando el algoritmoFindMaxima. A la izquierda, en una imagen sin preprocesar, el ruido provoca un resul-tado incorrecto (7281 componentes). A la derecha se obtienen 30 componentes conexashabiendo aplicado antes el filtro de Gauss con σ = 2.

En nuestro caso, el algoritmo FindMaxima forma parte de un plugin desa-rrollado por el grupo y denominado SynapCountJ [2], que tiene como objetivo

Page 61: Análisis matemático de rutinas de procesamiento de imágenes

Capıtulo 4. Algoritmo FindMaxima 53

el estudio de la densidad sinaptica. El uso que se da a este algoritmo dentro deeste plugin es el siguiente: una vez la imagen ha sido preprocesada (trazadaslas regiones de estudio y binarizada) utilizamos FindMaxima para el calculode las componentes conexas, las cuales por las tecnicas de preprocesamientoanteriores, sabemos que representan las sinapsis (conexiones entre dendritasy axones de diferentes neuronas) producidas dentro de una neurona en unmomento determinado. Con este algoritmo conseguimos calcular de manerarapida el numero de sinapsis.

Page 62: Análisis matemático de rutinas de procesamiento de imágenes
Page 63: Análisis matemático de rutinas de procesamiento de imágenes

Conclusiones

En este Trabajo Fin de Grado se han estudiado las propiedades matematicasde una serie de algoritmos pertenecientes a la plataforma ImageJ, dedicadaal procesamiento de imagenes digitales en el ambito biomedico. La principalconclusion que se desprende de nuestro estudio es que, pese a algunos erroresmenores, el software es suficientemente fiable y, con una razonable cantidadde esfuerzo, es posible llegar a entender los fundamentos matematicos queexplican el buen rendimiento de los programas, ası como la relacion directaentre los principios matematicos y las lıneas de codigo de los programas.Por otro lado, a partir del analisis del codigo, se ha dado una descripcionmatematica precisa de los algoritmos que no disponıan de una, y se hanestudiado los detalles de la implementacion del resto.

Esta investigacion puede ser tambien interpretada como una primera fasede analisis, necesaria, en un proyecto mas amplio para verificar (por medio deherramientas semi-automatizadas) la correccion de los programas, siguiendola lınea que se abrio en trabajos como [9].

55

Page 64: Análisis matemático de rutinas de procesamiento de imágenes

Referencias

[1] ImageJ/Fiji, imagej.nih.gov/ij/

[2] Spineup, www.spineup.es

[3] W. Bailer, Writing ImageJ Plugins - A tutorial. www.gm.fh-koeln.de/~konen/WPF-BV/tutorial-ImageJ_V1.71.pdf

[4] J. Burge, W. Burger, Principles of Digital Image Processing: Ad-vanced Methods. Sringer (2013)

[5] A. Deluca & S. Termini, A definition of a non-probabilistic entropyin the setting of fuzzy set theory, Int. Control 20, 301-312 (1972). www.sciencedirect.com/science/article/pii/S0019995872901994

[6] Huang, L-K & Wang, M-J J, Image thresholding by mini-mizing the measure of fuzziness, Pattern Recognition 28(1): 41-51 (1995). www.ktl.elf.stuba.sk/study/vacso/Zadania-Cvicenia/Cvicenie_3/TimA2/Huang_E016529624.pdf

[7] Ridler, TW & Calvard, Picture thresholding using an iterative se-lection method, IEEE Transactions on Systems, Man and Cybernetics 8:630-632 (1978). ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=4310039

[8] A. Cattaneoa, I. Larchera, I. Ruggerib, C. Herrera &M. Biasonia, ”Metodos de umbralizacion de imagenes digitalesbasados en entropıa de Shannon y otros”Mecanica Computacio-nal XXX: 2785-2805 (2011). www.cimec.org.ar/ojs/index.php/mc/article/viewFile/3951/3868

[9] J. Heras, G. Mata, A. Romero, J. Rubio y R. Saenz, Verifyinga platform for digital imaging: a multi-tool strategy, Lecture Notes inArtificial Intelligence 7961, 66–81 (2013). arxiv.org/abs/1303.1420

56