Está en la página 1de 36

Computacin De Alta Performance

DETECCIN DE BORDES Y AFINADO

Informe Final Marzo 2002 Facultad de Ingeniera Universidad de la Repblica

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

Tabla de Contenido

Planteo del Problema................................................................................................. 1


1.1 1.2 1.3 Intensidad ...................................................................................................................... 1 Deteccin de los Bordes................................................................................................ 1 Afinado de los Bordes ................................................................................................... 3

Descripcin de la Solucin........................................................................................ 4
2.1 2.2 2.3 2.4 Metodologa y Desarrollo ............................................................................................. 4 Paralelizacin de las Operaciones................................................................................ 5 Pseudocdigo ................................................................................................................ 6 Formato de la Imagen ................................................................................................... 8

3 4 5

Anlisis de Speed Up ................................................................................................ 9 Conclusiones ........................................................................................................... 15 Bibliografa ............................................................................................................. 16

Apndice A: La Entrega ................................................................................................. 17 Apndice B: Cdigo Fuente de la Aplicacin ................................................................ 18

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

1 Planteo del Problema


A modo de enunciado, el problema analizado en el proyecto es el siguiente: Detectar los bordes de una imagen, afinarlos hasta que sean del grosor de un pixel y generar con ellos una imagen binaria resultante. El resto del captulo explica como obtener la intensidad de un color a partir de su composicin RGB (1.1), qu son los bordes de una imagen y cmo se detectan (1.2) y finalmente, cmo se afinan los bordes (1.3).

1.1 Intensidad
Los formatos ms comunes en los que se guardan y comprimen las imgenes digitales utilizan el modelo RGB para la representacin de los colores. Este modelo se basa en un sistema Cartesiano de tres ejes: rojo (R), verde (G) y azul (B). Un color cualquiera C se representa mediante un vector de componentes (cR, cG, cB), donde cX es generalmente un valor natural entre 0 y 255. Esta forma de representacin no es til para el proceso de deteccin de bordes, que si requiere el valor de intensidad de cada color. La ecuacin para obtener ese valor a partir de la composicin RGB es la siguiente:

I = 0.299c R + 0,587cG + 0,114c B

(1.11)

donde I es la intensidad y cR, cG y cB son los componentes RGB del color. Esta ecuacin se desprende de la definicin de otro modelo de color denominado YIQ y su discusin supera el nivel de este informe. Por mayor detalle sobre este tema, ver [1].

1.2 Deteccin de los Bordes


Un borde es una frontera entre dos regiones de una imagen con niveles de intensidad relativamente distintos. Los algoritmos de deteccin de bordes se basan generalmente en la bsqueda de cambios abruptos en los niveles de intensidad de la imagen. Utilizan conceptos como el gradiente o el laplaciano de una funcin. En la prctica, la manera ms comn de buscar estas discontinuidades es pasar una o ms mscaras por cada pixel (x, y) de la imagen y tratar de decidir localmente si este pertenece a un borde o no, segn los valores de intensidad de sus vecinos. Una mscara no es otra cosa sino una matriz de coeficientes. La Figura 1-1 muestra una mscara general de 3 3 puntos. La posicin central corresponde al pixel (x, y) por el que pasa (llamado tambin centro) y las ocho restantes a sus vecinos directos. Se llama respuesta de la mscara (R) a la sumatoria de los productos entre los coeficientes wi y los niveles de intensidad de los pixeles respectivos bajo la mscara. Es decir, que la respuesta de la mscara en cualquier pixel de la imagen es:

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

Computacin de Alta Performance - 2001


9

Deteccin de Bordes y Afinado

R = w1 I 1 + ... + w9 I 9 = wi I i
i =1

(1.21)

donde Ii es el valor de intensidad del pixel asociado al coeficiente wi de la mscara. En los bordes deben tomarse consideraciones especiales, como suponer que todo elemento de la mscara que quede fuera de la imagen tendr asociado un valor de intensidad cero.

w1 w4 w7
Figura 1-1

w2 w5 w8

w3 w6 w9

Mscara general de 3 3

Existen varios mtodos que utilizan mscaras para la deteccin de bordes. Se diferencian entre s por la dimensin de la mscara, los valores para los coeficientes wi y por la utilizacin que le dan al valor de la respuesta de la mscara. En este proyecto se aplic el mtodo denominado Compass Edge Detector. La razn para esta decisin es que es uno de los mtodos ms costosos de implementar dada la gran cantidad de clculos que requiere. Consiste en calcular, para todo pixel de la imagen, la respuesta a cada una de las ocho mscaras que utiliza. La mxima respuesta en valor absoluto ser el nuevo valor de intensidad asignado al pixel. Para este mtodo se puede elegir entre varios juegos de mscaras posibles. El que fue utilizado en el proyecto fue desarrollado por Kirsch y se lista en la Figura 1-2. 5 5 5 -3 5 -3 0 5 5 -3 -3 5 -3 0 5 -3 -3 5 3 5 -3 -3 5 0 -3 5 -3 -3 7 -3 -3 -3 -3 0 5 -3 5 5 4 5 5 -3 5 0 -3 -3 -3 -3 8

-3 0 -3 -3 -3 -3 1 -3 -3 -3 -3 0 -3 5 5 5 5

-3 -3 -3 2 -3 -3 -3 5 5 0 -3 5 -3 6

Figura 1-2 Mscaras de Kirsch

La etapa final del proceso es comparar la nueva intensidad de cada pixel contra un cierto valor de tolerancia para decidir cuales pixeles pertenecen a los bordes y cuales no segn su intensidad supere o no dicho valor. La tolerancia puede disminuirse o aumentarse para que el mtodo sea ms o menos sensible a los bordes. Es en esta etapa donde se genera una imagen binaria, necesaria para utilizar como entrada en la operacin de afinado. A todo pixel cuya intensidad sea mayor que la tolerancia se le asigna el color blanco. Se dice que estos son los pixeles del frente. Al resto de los pixeles en la imagen se les asigna el color negro y son llamados pixeles del

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

fondo. Este tipo de imgenes suele representarse como matrices de ceros y unos para fondo y frente respectivamente. Por ms detalles sobre los temas tratados en esta seccin u otros temas relacionados, ver [1], [2], [3] o [4].

1.3 Afinado de los Bordes


El afinado es una operacin morfolgica usada comunmente para limpiar las imgenes resultantes de los algoritmos detectores de bordes. Elimina gran parte del ruido que suelen dejar los detectores y afina todas las lneas hasta que quedan del grosor de un pixel. Normalmente se aplica a imgenes binarias y da como resultado otra imagen binaria. Para entender la operacin de afinado es necesario conocer los elementos estructurantes. Son patrones de valores especificados con respecto a un origen, representados generalmente mediante matrices rectangulares de distintos tamaos. La Figura 1-3 muestra los elementos estructurantes que se utilizan en el afinado de bordes. Todos son de 3 3 y con origen en el centro de la matriz (no siempre es as). Los valores que toman los elementos son: - 0: el pixel pertenece al fondo. - 1: el pixel pertenece al frente. - X: no importa el valor del pixel. 0 1 1 0 0 1 1 1 0 5 0 1 1 0 X 0 1 1 1 0 0 1 X 0 1 1 0 1 X 0 3 0 X 1 0 1 1 0 X 1 7 1 1 1 X 1 0

X 1 X

1 X 2 X 1 1 0 0 1 1 0 X 6

X 0 0 4 0 0 X 0 1 1 1 X 1 8

X 1 X

Figura 1-3

El proceso de afinado es iterativo. Un ciclo consiste en pasar cada uno de los elementos estructurantes (uno a la vez) por cada uno de los pixeles de la imagen. Comenzando con el 1, se ubica el pixel en el centro del elemento estructurante y se compara el patrn con el de su vecindario. Si el patrn coincide con el vecindario entonces el pixel del centro cambia su valor y pasa a formar parte del fondo. As hasta analizar todos los pixeles de la imagen. A continuacin se toma el siguiente elemento estructurante y se aplica de igual forma sobre la imagen resultante del paso anterior. As sucesivamente hasta que hayan pasado los 8 elementos. La condicin para finalizar es que luego de un ciclo completo no haya ocurrido un cambio de valor en ningn pixel. En el caso particular de los bordes, la operacin supone que la imagen est rodeada totalmente por pixeles que pertenecen al fondo. Por ms detalles sobre este tema, ver [1] y [2].

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

2 Descripcin de la Solucin
2.1 Metodologa y Desarrollo
A lo largo de todo el proceso se trabaja sobre la imagen de entrada que se carga en memoria como una matriz esttica de valores (estructuras RGB o enteros). Se puede ver la operacin total como un encadenamiento de clculos que se aplican a cada uno de esos valores. Esos clculos adems no involucran valores globales y casi no involucran a otros valores de la matriz. Es claro entonces que la metodologa a seguir para paralelizar la solucin era la descomposicin de datos. Fraccionar la imagen en varias franjas e implementar procesos que operen sobre cada una de ellas, reuniendo al final los resultados parciales para lograr la imagen resultante.
1 2 3 4 5
imagen_original = cargar_imagen () imagen_intensidad = hallar_intensidades (imagen_original) imagen_bordes = detectar_bordes (imagen_intensidad) imagen_final = afinar (imagen_bordes) salvar_imagen(imagen_final) Figura 2-1 Algoritmo serial simplificado

En la Figura 21 se lista un pseudocdigo simplificado donde se identifican las etapas ms importantes del algoritmo serial. La primera versin paralela que se implement consista en un proceso padre que realizaba la operacin de carga de la imagen, la divida en franjas y enviaba cada franja a un proceso hijo distinto. A medida que los hijos respondan con el resultado parcial iba armando la imagen resultante y finalmente guardaba el resultado en el disco. Cada hijo tena la lgica para realizar las etapas 2, 3 y 4. Las primeras mediciones revelaron rapidamente que la operacin de fraccionar y enviar las franjas de la imagen era muy costosa y ocupaba casi la totalidad del tiempo de ejecucin. Este resultado no era para nada interesante, por lo que se desarroll entonces una segunda versin paralela con modificaciones que ayudaran a solucionar ese problema. En primer lugar, el proceso padre se quedara con la ltima franja de la imagen para ahorrarse un empaquetado y envo. Como esto no fue suficiente, se elimin el mecanismo completo de fraccionamiento y se le agreg lgica a los procesos hijos para que pudieran efectuar ellos mismos la carga de la imagen. Para ese entonces las tareas especficas del proceso padre eran recibir los parmetros de entrada, crear los procesos hijos y salvar el resultado, por lo que pareci coherente unificar el cdigo de padres e hijos en un solo cdigo fuente para la aplicacin. Las funciones inherentes a cada tipo de proceso se encerraron dentro de controles que permite pvm para saber si una tarea tiene padre o no. Adems de esto, el cdigo fue concebido de tal forma que cuando se ejecuta en un solo procesador funciona como si fuera un programa serial. El pseudocdigo de la aplicacin se expone en la seccin 2.3 y el cdigo fuente aparece en el Apndice B de este documento.

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

2.2 Paralelizacin de las Operaciones


Al ejecutar la aplicacin inicia el proceso padre. Este se encarga de obtener los datos de entrada. Entre ellos se encuentra la cantidad de procesos total que quiere el usuario. Se crearn un nmero de procesos hijos igual al valor de este parmetro menos 1, porque el padre es considerado uno ms de los procesos que involucra la ejecucin. El padre mismo asignar, a cada uno de los hijos, un nmero identificatorio que indica sobre qu franja de la imagen deben trabajar (el -1 est reservado como nmero del padre). Comienza la seccin paralela de la aplicacin. Cada proceso realiza la carga total de la imagen y, con ayuda de su nmero asignado, identifica la franja que le corresponde para trabajar. Es importante destacar que los procesos guardan adems de su franja, las filas superior e inferior a la misma para evitar comunicaciones innecesarias entre procesos luego. Para manejar los casos borde del primer proceso y del padre (que toman siempre la primer y ltima franja respectivamente) la resolucin tomada fue sobrescribir al comienzo con negro la primer y ltima fila de pixeles de la imagen, suponiendo que esto no incide significativamente en la deteccin de bordes. De esta forma, la franja de trabajo del primer proceso comenzar en realidad en la segunda fila de pixeles y as puede utilizar la primera como superior. Analogamente, la franja del proceso padre llega en realidad hasta la penltima fila de pixeles de la imagen y utiliza la ltima como inferior. Quiere decir entonces que la zona total de trabajo que toma en cuenta un proceso cualquiera est formada por: una lnea superior, la franja que le corresponde y una lnea inferior. Adems, la primer lnea de la franja de trabajo es la inferior para el proceso anterior y la ltima lnea de la franja es la superior para el proceso siguiente.
LINEA SUPERIOR FRANJA DE TRABAJO LINEA INFERIOR

Modificada por el proceso anterior Lneas correspondientes al proceso. Modificada por el proceso siguiente

Figura 2-2 Estructura de la zona total de trabajo para un proceso cualquiera

El siguiente paso es hallar el valor de intensidad para cada pixel de la zona total de trabajo, utilizando la ecuacin (1.11). Estos valores se guardan en una nueva matriz de intensidades y al finalizar esta operacin ya es seguro eliminar de memoria la imagen total. Comienza entonces la etapa de deteccin de bordes en la franja de trabajo (no sobre toda la zona de trabajo). Se aplica el mtodo explicado anteriormente hallando la respuesta de cada pixel a las mscaras de Kirsch, calculando la nueva intensidad y comparndola contra la tolerancia. El resultado es una nueva matriz con valores binarios: los pixeles de los bordes detectados al frente, los dems al fondo. En esta etapa no hay comunicacin alguna entre los procesos gracias a que se guardan las lneas superior e inferior a la franja. (recordemos que las mscaras se aplican sobre una vecindad del pixel). Finalmente, se realiza la etapa de afinado en la franja de trabajo, a partir de los valores en la matriz binaria. Comienza con el intercambio de lneas bordes entre procesos. Un proceso cualquiera enva la primer lnea de la franja de trabajo al proceso anterior y la ltima lnea al proceso siguiente. A continuacin recibe la lnea superior del proceso anterior y la inferior del proceso siguiente que son los encargados de afinarlas (ver Figura 22). Para poder paralelizar el afinado, el proceso debe hacer una copia temporal de la franja de trabajo, realizar el afinado sobre esa copia y registrar los posibles cambios en la franja original. Si no se hiciera as, el proceso i solo podra
Juan Diego Ferr Enrico Pizzorno Nicols Sierra

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

empezar despus que termine el i-1 y le enve la lnea superior modificada en la iteracin. En definitiva, no habra procesamiento paralelo. Despus de pasar los ocho elementos estructurantes por la franja, los procesos reportan al padre si hubo cambios o no en esa iteracin y quedan a la espera de una respuesta. En caso que haya ocurrido al menos un cambio en alguna de las franjas el padre les indica a todos los procesos que se debe realizar una iteracin ms. Si por el contrario no hubo cambios, avisa a los procesos que termin la operacin y que le enven los resultados. Al recibirse todas las franjas termina la seccin paralela de la aplicacin y comienza la serial. Se arma la imagen y se guarda en el disco.

2.3 Pseudocdigo
Inicializo las mscaras y elementos estructurantes Si soy la tarea padre Pido los parmetros de entrada: nombre del archivo de entrada, nombre del archivo de salida, tolerancia, cantidad de procesos Si la cantidad de procesos es mayor a 1 Creo (cantidad de procesos - 1) tareas nuevas Para cada tarea creada Asigno a la tarea un nmero correlativo Envo a la tarea: su nmero, el nmero de la tarea anterior, el nmero de la tarea siguiente, la cantidad total de tareas, el nombre del archivo de entrada, la tolerancia. Fin Para Sino Soy la nica tarea, ejecucin serial Fin Si Sino Soy un hijo Recibo los datos enviados por el padre Fin Si Cargo la imagen de entrada Divido el alto de la imagen entre el nmero de procesos y me quedo solo con la franja que me corresponde Guardo tambin las lneas superior e inferior a la franja Inicializo la matriz de intensidades Para cada pixel en la zona total de trabajo Obtengo el valor de intensidad a partir de las componentes RGB del pixel Registro ese valor en la matriz de intensidades Fin Para Libero la memoria de la imagen original porque puede ocupar demasiado
Juan Diego Ferr Enrico Pizzorno Nicols Sierra

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

Inicializo la matriz binaria Para cada pixel en la franja de trabajo Inicializo el nuevo valor de intensidad en menos infinito Para cada mscara Calculo la respuesta del pixel a la mscara Si el valor absoluto de la respuesta es mayor al nuevo valor de intensidad Actualizo el nuevo valor de intensidad Fin Si Fin Para Si el nuevo valor de intensidad es mayor que la tolerancia Registro el pixel como pixel del frente en la matriz binaria Sino Registro el pixel como pixel del fondo en la matriz binaria Fin Si Fin Para Mientras el padre no avise que termina la operacin Para cada elemento estructurante Envo las filas de la matriz binaria que precisan mis tareas vecinas Recibo las filas de la matriz binaria que preciso de las tareas vecinas Copio la matriz binaria a una matriz temporal Para cada pixel en la copia temporal Comparo el elemento estructurante y el vecindario del pixel Si coinciden Cambio el valor del pixel en la matriz binaria Sino Copio el valor del pixel en la matriz binaria Fin Si Fin Para Fin Para Si no soy el padre Aviso al proceso padre si ocurrieron o no cambios Sino Recibo los avisos de todas las tareas Si alguna reporto cambios Aviso a todas las tareas que deben seguir trabajando Sino Aviso a todas las tareas que termin la operacin Fin Si Fin Si Fin Mientras Si no soy el padre Envo al padre la matriz binaria Sino Inicializo la imagen resultado Recibo las matrices parciales de cada tarea Ordeno las matrices en la imagen resultado Guardo la imagen resultado en disco Fin Si

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

2.4 Formato de la Imagen


Las imgenes utilizadas por la aplicacin deben estar en formato PNG. Las razones que influyeron en esta eleccin son: Permite cargar imgenes muy grandes en muy poco tiempo, propiedad esta esencial para realizar las pruebas eficientemente. Existen actualmente libreras instaladas en las mquinas utilizadas para el proyecto que permiten la manipulacin de archivos con ese formato (libpng). La libpng guarda la imagen en memoria como una matriz de bytes, donde 3 bytes consecutivos representan el color en RGB de cada uno de los puntos de la misma. De esta manera, se recorre directamente la matriz para ir calculando las intensidades de todos los puntos de la imagen. Antes de decidir por este formato y esta librera se prob con pixmaps (xpm) usando libxpm. Adems de tardar mucho ms en levantar la imagen desde un archivo, la representacin de la imagen en memoria era una matriz donde cada punto estaba representado por un string (char*) con el formato RRGGBB. Esto implicaba un esfuerzo mayor de procesamiento al calcular las intensidades de cada punto (tener que pasar el texto correspondiente a un entero en base 16 a un entero). Una consideracin importante: las imgenes PNG pueden tener distinto nmero de canales segn como se hayan guardado. La aplicacin implementada solo levanta imgenes salvadas con tres o cuatro canales, RGB o RGB + alfa respectivamente. La imagen a resultante tendr las siguientes propiedades: Compresin por defecto. Sin filtros. No interlaceada. Sistema de colores RGB. Profundidad de colores (8 o 16).

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

3 Anlisis de Speed Up
Para el anlisis de Speed Up se tomaron en cuenta dos variables: la cantidad de procesadores y el tamao de la imagen. Se ejecut la aplicacin con 1, 2, 3, 4, 5, 10 y 15 procesadores. En cada procesador corra un solo proceso a la vez. Cada una de esas configuraciones se prob con imgenes de distinto tamao. Ms precisamente, se utiliz una misma imagen base y se multiplic su tamao linealmente, creciendo hasta cuatro veces el tamao original (ver Figura 31). Para cada uno de estos escenarios se tomaron varios tiempos (al menos cinco) y se registr un promedio de los mismos. a.

b.

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

c.

Figura 3-1 Imagen utilizada en las pruebas: (a) original; (b) luego de detectados los bordes; (c) resultado final Las imgenes (b) y (c) son en realidad el negativo del resultado.

Cabe destacar que si bien la tolerancia utilizada en el proceso de deteccin de bordes es una variable de entrada de la aplicacin, para el anlisis se eligi un valor adecuado (800) y se dej fijo a lo largo de todas las pruebas. Los resultados son:

Cantidad de Procesos 1 2 3 4 5 10 15

711 x 500 Tiempo de Ejecucin 13,2966934 5,6563522 4,9005778 3,9117312 4,6185766 4,7181058 5,2137448

Speed Up 1 2,350754149 2,713290951 3,399183819 2,878959158 2,818227052 2,550315351

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

10

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

Imagen 711 x 500


Tiempo de ejecucin (seg)
14 12 10 8 6 4 2 0 1 2 3 4 5 10 15

Cantidad de Procesadores

Imagen 711 x 500


4 3,5 3 2,5 2 1,5 1 0,5 0 1 2 3 4 5 10 15

Speed Up

Cantidad de Procesadores

Cantidad de Procesos 1 2 3 4 5 10 15

Imagen de 1422 x 1000 Tiempo de Ejecucin 34,4734924 12,2838688 10,4306604 9,8579366 10,7161666 12,742643 16,311438

Speed Up 1 2,8064035 3,305015318 3,497029226 3,216961222 2,705364374 2,113455135

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

11

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

Imagen 1422 x 1000


40 35 30 25 20 15 10 5 0 1 2 3 4 5 10 15

Tiempo de Ejecucin (seg)

Cantidad de Procesadores

Imagen 1422 x 1000


4 3,5 3 2,5 2 1,5 1 0,5 0 1 2 3 4 5 10 15

Speed Up

Cantidad de Procesadores

Cantidad de Procesos 1 2 3 4 5 10 15

2133 x 1500 Tiempo de Ejecucin 72,9383650 23,5107546 20,4724524 18,2463496 20,2408022 26,1816892 27,52489667

Speed Up 1 3,10234045 3,562756605 3,997422312 3,603531336 2,785854054 2,649905134

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

12

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

Imagen 2133 x 1500


80 70 60 50 40 30 20 10 0 1 2 3 4 5 10 15

Tiempo de Ejecucin (seg)

Cantidad de Procesadores

Imagen 2133 x 1500


5 4

Speed Up

3 2 1 0 1 2 3 4 5 10 15

Cantidad de Procesadores

Cantidad de Procesos 1 2 3 4 5 10 15

2844 x 2000 Tiempo de Ejecucin 182,9160993 46,9939818 33,6097168 27,9526448 28,7455304 41,0937004 45,901573

Speed Up 1 3,892330299 5,442357647 6,543785054 6,363288369 4,45119562 3,984963636

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

13

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

Imagen 2844 x 2000


Tiempo de Ejecucin (seg)
200 150 100 50 0 1 2 3 4 5 10 15

Cantidad de Procesadores

Imagen 2844 x 2000


7 6 5 4 3 2 1 0 1 2 3 4 5 10 15

Speed Up

Cantidad de Procesadores

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

14

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

4 Conclusiones
La conclusin ms importante que se desprende de las pruebas es que la paralelizacin de la aplicacin influy muy positivamente en la performance. En cualquiera de los casos el tiempo de ejecucin serial es mayor que el de la ejecucin paralela, no importa la cantidad procesadores. Cabe destacar sin embargo que los mejores tiempos se dieron al correr la aplicacin con 4 procesadores. Con menos los tiempos eran ms altos y con ms comenzaban a subir nuevamente. Podra decirse (al menos para la imagen utilizada) que 4 sera el nmero ptimo de procesadores para la ejecucin. Una de las razones para que la paralelizacin brinde tan buenos resultados es que resuelve el problema del swapping. Sucede que a medida que la imagen crece se requiere ms memoria para levantarla y manipularla. Como la memoria de las mquinas de prueba se agotaba rapidamente, comenzaban a bajar a disco las pginas que no utilizaban y a levantar las que si precisaban. Los accesos a disco son muy costosos en cuanto al tiempo que requieren. Al fraccionar la imagen se logra disminuir la cantidad de memoria necesaria y la cantidad de accesos al disco por intercambio de pginas. Es por eso que los mejores valores de Speed Up se dieron trabajando con las imgenes ms grandes. Finalmente, recordar que result ms eficiente que cada proceso cargue la imagen completa a que la cargue el proceso padre, la fragmente, la empaquete y la enve a los dems.

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

15

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

Bibliografa
[1] GONZALES R. C., WOOD R. E. Digital Image Processing. Addison Wesley, 1993. FISHER R., PERKINS S., WALKER A., WOLFART E. Image Processing Learning Resources. Department of Artificial Intelligence University of Edinburgh http://www.dai.ed.ac.uk/HIPR2 CORTIJO BON R. J. Apuntes para Introduccin General a la Robtica. Dpto. de Ciencias de la Computacin e Inteligencia Artificial Universidad de Granada. http://www-etsi2.ugr.es/depar/ccia/robotica/indice_apuntes.html Introduccin al Procesado de Imagen. Grupo de Procesado de Imagen Universidad de Vigo http://wgpi.tsc.uvigo.es/libro/procesim/procesim.htm GEIST A., BEGUELIN A., DONGARRA J., JIANG W., MANCHEK R., SUNDERAM V. PVM: Parallel Virtual Machine A User Guide and Tutorial for Networked Parallel Computing. MIT Press, 1994. http://www.netlib.org/pvm3/book/pvm-book.html

[2]

[3]

[4]

[5]

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

16

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

Apndice A: La Entrega
Los archivos entregados se encuentran en el directorio HOME del grupo y son los siguientes: master.cpp Cdigo fuente de la aplicacin implementada. Informe Final.pdf Este documento.

Para compilar el cdigo se utiliz el siguiente comando:


g++ -g -I/usr/local/opt/pvm-3.4.3/include -I/usr/local/opt/libpng-1.0.9/include -I/usr/local/opt/zlib-1.1.3/include -DSYSVBFUNC -DSYSVSTR -DNOGETDTBLSIZ -DSYSVSIGNAL -DNOWAIT3 -DNOUNIXDOM -DRSHCOMMAND=\"/usr/bin/ssh\" -o hpc master.cpp -L/lib/X86SOL2 -lpvm3 -L/usr/local/opt/pvm-3.4.3/lib/X86SOL2 -L/usr/local/opt/libpng-1.0.9/lib -R/usr/local/opt/libpng-1.0.9/lib -L/usr/local/opt/zlib-1.1.3/lib -lnsl -lsocket lpng

El nombre de la aplicacin debe ser hpc. Los parmetros de entrada son: nombre del archivo con la imagen de entrada nombre del archivo para la imagen resultado valor de tolerancia para la deteccin de bordes cantidad de procesos total a utilizar El nombre del archivo con la imagen de entrada debe incluir la ruta completa desde el directorio raz. De otra forma los procesos hijos no lo encontrarn. La cantidad de procesos debe ser mayor o igual a 1.

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

17

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

Apndice B: Cdigo Fuente de la Aplicacin


#include #include #include #include #include #include #include #include #include #include #include #include <stdio.h> <stdlib.h> <unistd.h> <iostream.h> <png.h> <string.h> <math.h> <sys/time.h> <stddef.h> <limits.h> <float.h> <pvm3.h>

//#define DEBUG 0 #define THINNING 0 #define MASTIEMPOS 0 /* Indicacin entre tareas de filtrado si hubieron cambios */ #define FILA_SIN_CAMBIOS 0 #define FILA_DE_ARRIBA 1 #define FILA_DE_ABAJO 2 /* Indicacin si hay cambios o no (mensajes desde y hacia el master) */ #define NO_HAY_CAMBIOS 0 #define HAY_CAMBIOS 1 /* Los identificadores de los mensajes entre tareas */ #define MSG_IMAGEN 1 #define MSG_FILA 2 #define MSG_SEGUIR 3 #define MSG_RESULT 4 typedef struct { int inicio; int fin; } tramo; /* Matrices de Kirsch para el clculo del gradiente */ int H[8][3][3] = {{{ 5, {-3, {-3, {{-3, {-3, {-3, {{-3, {-3, {-3, {{-3, {-3, {-3, {{-3, {-3, { 5, {{-3, { 5, { 5, {{ 5, { 5, { 5, {{ 5, 5, 5}, // Matriz para la direccin norte 0, -3}, -3, -3}}, 5, 5}, // Matriz para la direccin Noreste 0, 5}, -3, -3}}, -3, 0, -3, 5}, // Matriz para la direccin Este 5}, 5}},

-3, -3}, // Matriz para la direccin Sureste 0, 5}, -5, 5}}, -3, -3}, // Matriz para la direccin Sur 0, -3}, 5, 5}}, -3, -3}, // Matriz para la direccin Suroeste 0, -3}, 5, -3}}, -3, -3}, // Matriz para la direccin Oeste 0, -3}, -3, -3}}, 5, -3}, // Matriz para la direccin Oeste

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

18

Computacin de Alta Performance - 2001


{ 5, 0, -3}, {-3, -3, -3}}}; /* Elementos estructurantes para el #define X 2 char B[8][3][3] ={{{0, 0, 0}, {X, 1, X}, {1, 1, 1}}, {{X, 0, 0}, {1, 1, 0}, {1, 1, X}}, {{1, X, 0}, {1, 1, 0}, {1, X, 0}}, {{1, 1, X}, {1, 1, 0}, {X, 0, 0}}, {{1, 1, 1}, {X, 1, X}, {0, 0, 0}}, {{X, 1, 1}, {0, 1, 1}, {0, 0, X}}, {{0, X, 1}, {0, 1, 1}, {0, X, 1}}, {{0, 0, X}, {0, 1, 1}, {X, 1, 1}} }; thinning */

Deteccin de Bordes y Afinado

/** * Aplica la mscara h a la imagen img en la posicin (m,n), * devolviendo el gradiente en la direccin de h para dicho pixel. */ float aplicarMascara(float **img, int h[3][3], int m, int n) { float grad = 0; float a0, a1, a2, a3, a4, a5, a6, a7; a0 a1 a2 a3 a4 a5 a6 a7 = = = = = = = = img[m -1 ][n img[m -1][n]; img[m - 1][n + img[m][n + 1]; img[m + 1][n + img[m + 1][n]; img[m + 1][n img[m][n - 1]; 1]; 1]; 1]; 1];

grad =

a0 * h[0][0] + a1 * h[0][1] + a2 * h[0][2] + a7 * h[1][0] + a3 * h[1][2] + a6 * h[2][0] + a5 * h[2][1] + a4 * h[2][2];

return grad; } /** * Funciones auxiliares para la lectura/escritura de pngs */ int png_read_file(char* file, png_structp &png_ptr, png_infop &info_ptr) { char cab[8]; FILE *fp; fp = fopen(file, "rb"); if (!fp) { return 1; }

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

19

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

/* Lectura del cabezal para asegurar que sea PNG */ fread(cab, 1, 8, fp); if (png_sig_cmp((png_byte*)cab, 0, 8)) { return 2; } /* Creacin de estructuras auxiliares de la imagen */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); if (!png_ptr) { return 3; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return 4; } /* Indicarle a libpng la entrada de la imagen */ png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); /* Carga de la imagen en memoria */ png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); return 0; } /* Destruye la imagen en memoria (si se us png_read_file) */ void png_destroy_read(png_structp &png_ptr, png_infop &info_ptr) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); } /** * La imagen a guardar tendr las siguientes propiedades: * * 1) Compresin por defecto. * 2) Sin filtros. * 3) No interlaceada. * 4) Sistema de colores RGB. * 5) Profundidad de colores (8 o 16). */ int png_write_file(char *file, int width, int height, row_pointers) { FILE *fp; png_structp png_ptr; png_infop info_ptr; fp = fopen(file, "wb"); if (!fp) { return 1; } /* Creacin de estructuras auxiliares de la imagen */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL); if (!png_ptr) { return 2; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); } /* Para que libpng se encargu de guardar el archivo */ png_init_io(png_ptr, fp); /* Setear los valores de las estructuras */

int

bit_depth,

png_bytepp

(png_voidp)NULL,

NULL,

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

20

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_ABSOLUTE); png_set_rows(png_ptr, info_ptr, row_pointers); /* Escribe la imagen en el archivo */ png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); /* Me aseguro que la escriba */ png_write_flush(png_ptr); return 0; } /* Destruye la informacin que ya se guard a disco (con png_write_file) */ void png_destroy_write(png_structp &png_ptr, png_infop &info_ptr) { png_destroy_write_struct(&png_ptr, &info_ptr); } /* Crea una matriz de png_bytes (es decir un png_bytepp) */ png_bytepp png_create_matrix(int filas, int columnas) { png_bytepp matriz; matriz = new (png_byte*)[filas]; for (int i = 0; i < filas; i++){ matriz[i] = new png_byte[columnas]; } return matriz; }

/** * Segundos entre dos marcas de tiempo (timeval). */ struct timeval * difTiempo(struct timeval *fin, struct timeval *principio) { struct timeval *res = new struct timeval; int carry = 0; if ( principio->tv_usec > fin->tv_usec ){ carry = 1; res->tv_usec = principio->tv_usec - fin->tv_usec; } else { res->tv_usec = fin->tv_usec - principio->tv_usec; } res->tv_sec = fin->tv_sec - principio->tv_sec - carry; return res; } /** * Carga la imagen en formato png. */ void cargarImagen(char* file, int &alto, int &ancho, int &canales, png_bytepp &matriz, png_structp &png_read, png_infop &png_read_info) { struct timeval *inicio = new struct timeval, *final = new struct timeval, *espera; cout << "Cargando imagen " << file <<" ...\n"; gettimeofday(inicio, NULL); if (png_read_file(file, png_read, png_read_info) != 0) { cout << "Error al cargar la imagen desde " << file << "\n"; pvm_exit(); exit(1); } gettimeofday(final, NULL);

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

21

Computacin de Alta Performance - 2001


/* Slo soportamos 3 o 4 canales por punto en la imagen */ canales = png_get_channels(png_read, png_read_info); switch (canales) { case 3: cout << "Imagen RGB\n"; break; case 4: cout << "Imagen RGB + ALPHA\n"; break; default: cout << "Nmero de canales de la imagen no soportado\n"; pvm_exit(); exit(1); } alto = png_get_image_height(png_read, png_read_info); ancho = png_get_image_width(png_read, png_read_info); matriz = png_get_rows(png_read, png_read_info); espera = difTiempo(final, inicio);

Deteccin de Bordes y Afinado

cout << "Tamao de la imagen: " << ancho << " x " << alto << "\n"; cout << "Tiempo de carga: " << espera->tv_sec << "." << espera->tv_usec << " segundos\n\n"; } /** * Divide la imagen entre los procesos indicados, devolviendo la fila * donde empieza el tramo del proceso master (el ltimo tramo). * 1) Los procesos deben estar creados. */ void dividirImagen(int alto, int ancho, int canales, png_bytepp matriz, int pos, int ntask, int &desde, int &hasta) { int altodiv; /* Alto de los fragmentos (puedo tener un resto, se lo lleva el master) * Hay que recodar que las filas 0 y alto - 1 no se filtran */ altodiv = (alto - 2) / (ntask + 1); if (altodiv == 0) { cout << "La imagen NO se puede dividir en una banda para cada proceso\n"; pvm_exit(); exit(1); } if (pos desde } else { desde } if (pos hasta } else { hasta } } void enviarDatos(char *input, float tol, int *tids, int ntask) { int ihijo, tid, ant, sig, bufid; struct timeval *inicio, *fin, *total; cout << "Enviando informacin a las " << ntask << " tareas...\n\n"; inicio = new struct timeval; fin = new struct timeval; total = new struct timeval; gettimeofday(inicio, NULL); == 0) { = 0; // El primero

= pos * altodiv; == ntask) { // El master se lleva todo el resto = alto; = desde + altodiv + 2;

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

22

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

for (ihijo = 0; ihijo < ntask; ihijo++) { tid = tids[ihijo]; /* Resolvemos a con quin tiene que cambiar informacin el hijo */ if (ihijo == 0) { ant = -1; } else { ant = tids[ihijo - 1]; } if (ihijo == ntask - 1) { sig = pvm_mytid(); } else { sig = tids[ihijo + 1]; } #ifdef DEBUG cout << "Informacin de tarea "<< ihijo << ":\n" << "tid = " << tid << "\n" << "anterior = " << ant << "\n" << "siguiente = " << sig << "\n\n"; #endif bufid = pvm_initsend(PvmDataDefault); pvm_pkint(&ihijo, 1, 1); pvm_pkint(&ant, 1, 1); pvm_pkint(&sig, 1, 1); pvm_pkint(&ntask, 1, 1); pvm_pkstr(input); pvm_pkfloat(&tol, 1, 1); if (pvm_send(tid, MSG_IMAGEN) != 0) { pvm_perror("Error al enviar datos a tarea de filtrado\n"); pvm_exit(); exit(1); } } gettimeofday(fin, NULL); total = difTiempo(fin, inicio); cout << "Tiempo utilizado: " << total->tv_sec << "." << total->tv_usec << "\n"; } void recibirDatos(int &pos, int &ant, int &sig, int &ntask, char* &input, float &tol) { int bufid; input = new char[255]; bufid = pvm_recv(-1, MSG_IMAGEN); if (bufid < 0) { pvm_perror("Error al recibir datos de tarea \"master\"\n"); pvm_exit(); exit(1); } pvm_upkint(&pos, 1, 1); pvm_upkint(&ant, 1, 1); pvm_upkint(&sig, 1, 1); pvm_upkint(&ntask, 1, 1); pvm_upkstr(input); pvm_upkfloat(&tol, 1, 1); } /** * Crear matriz de intensidades a partir de fragmento de imagen. * Se debe indicar la fila inicial del fragmento (desde) y la final + 1 (hasta).

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

23

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

*/ float** calcularIntensidades(int alto, int ancho, int canales, png_bytepp matriz, int desde, int hasta) { int altodiv, i, j, k; float **pixeles; png_byte rojo, verde, azul; altodiv = hasta - desde; pixeles = new (float*)[altodiv]; for (i = 0; i < altodiv; i++) { pixeles[i] = new float[ancho]; for (j = 0; j < ancho; j++) { k = j * canales; rojo = matriz[i + desde][k]; verde = matriz[i + desde][k + 1]; azul = matriz[i + desde][k + 2]; pixeles[i][j] = 0.299 * rojo + 0.587 * verde + 0.114 * azul; } } return pixeles; } /** * Creacin de matriz de bytes de tamao alto x ancho */ char **crearMatriz(int alto, int ancho) { char **matriz; matriz = new (char*)[alto]; for (int i = 0; i < alto; i++){ matriz[i] = new char[ancho]; } return matriz; } /** * Aplica el elemento estructurante B a la imagen "bordes" en la * posicin (i,j). Devuelve true si el pixel (i,j) cambia de valor * y false en caso contrario. Siempre se guarda el valor del pixel * en la posicin (i,j) de la matriz "nueva". */ bool aplicarThinning(char **bordes, char **nueva, char B[3][3], int i, int j, int alto, int ancho) { char a[3][3]; int m, n; /* Si el pixel no es un borde no hago nada y devuelvo false */ if(bordes[i][j] == 0){ nueva[i][j] = 0; return false; } a[1][1] = bordes[i][j]; /* Si el pixel est en algun borde asumo que la imagen est rodeada de 0 */ if ((i == 0) || (j == 0) || (i == alto - 1) || (j == ancho - 1)) { /* Esquina superior izquierda */ if ((i == 0) && (j == 0)) { a[0][0] = a[0][1] = a[0][2] = a[2][0] = a[1][0] = 0; a[2][2] = bordes[i + 1][j + 1]; a[1][2] = bordes[i][j + 1]; a[2][1] = bordes[i + 1][j]; } /* Esquina superior derecha */ else if ((i == 0) && (j == ancho - 1)) {

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

24

Computacin de Alta Performance - 2001


a[0][0] a[2][1] a[2][0] a[1][0] } /* Esquina inferior dizquierda */ else if ((i == alto - 1) && (j == 0)){ a[0][0] = a[1][0] = a[2][0] = a[2][2] = a[2][1] = 0; a[0][1] = bordes[i -1][j]; a[0][2] = bordes[i - 1][j + 1]; a[1][2] = bordes[i][j + 1]; } /* Esquina inferior derecha */ else if((i == alto - 1) && (j == ancho -1)){ a[0][2] = a[1][2] = a[2][2] = a[2][1] = a[2][0] = 0; a[0][0] = bordes[i -1 ][j - 1]; a[0][1] = bordes[i -1][j]; a[1][0] = bordes[i][j - 1]; } /* En el borde superior pero no en las esquinas */ else if (i == 0){ a[0][0] = a[0][1] = a[0][2] = 0; a[1][2] = bordes[i][j + 1]; a[2][2] = bordes[i + 1][j + 1]; a[2][1] = bordes[i + 1][j]; a[2][0] = bordes[i + 1][j - 1]; a[1][0] = bordes[i][j - 1]; } /* En el borde izquierdo pero else if(j == 0){ a[0][0] = a[2][0] = a[1][0] a[0][1] = bordes[i -1][j]; a[0][2] = bordes[i - 1][j + a[1][2] = bordes[i][j + 1]; a[2][2] = bordes[i + 1][j + a[2][1] = bordes[i + 1][j]; } no en un vrtice */ = 0; 1]; 1]; = = = = a[0][1] = a[0][2] = a[1][2] = a[2][2] = 0; bordes[i + 1][j]; bordes[i + 1][j - 1]; bordes[i][j - 1];

Deteccin de Bordes y Afinado

/* En el borde derecho */ else if(j == ancho -1){ a[0][2] = a[1][2] = a[2][2] = 0; a[0][0] = bordes[i -1 ][j - 1]; a[0][1] = bordes[i -1][j]; a[2][1] = bordes[i + 1][j]; a[2][0] = bordes[i + 1][j - 1]; a[1][0] = bordes[i][j - 1]; } /* En el borde inferior */ else if(i == alto - 1){ a[2][2] = a[2][1] = a[2][0] = 0; a[0][0] = bordes[i -1 ][j - 1]; a[0][1] = bordes[i -1][j]; a[0][2] = bordes[i - 1][j + 1]; a[1][2] = bordes[i][j + 1]; a[1][0] = bordes[i][j - 1]; } } else { a[0][0] a[0][1] a[0][2] a[1][2] a[2][2] a[2][1] a[2][0] a[1][0] } = = = = = = = = bordes[i -1 ][j bordes[i -1][j]; bordes[i - 1][j + bordes[i][j + 1]; bordes[i + 1][j + bordes[i + 1][j]; bordes[i + 1][j bordes[i][j - 1]; 1]; 1]; 1]; 1];

/* Ahora recorro el elemento estructurante para ver si coincide * con los pixeles. */ for(m = 0; m < 3; m++){ for(n = 0; n < 3; n++){

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

25

Computacin de Alta Performance - 2001


if(B[m][n] != X){ if(B[m][n] != a[m][n]){ nueva[i][j] = bordes[i][j]; return false; } } } } /* Coloco el pixel revisado como parte del fondo */ nueva[i][j] = 0; return true; }

Deteccin de Bordes y Afinado

/* Filtro paralelo: * tmaster Tarea "master". * tant Tarea que tiene el fragmento anterior. * tsig Tarea que tiene el fragmento siguiente. * tids[] Array con los identificadores de las tareas que estn filtrando * adems de la tarea actual. * ntask Cantidad de procesos que estn filtrando (adems de este). * alto Alto de la matriz de intensidades. * ancho Ancho de la matriz de intensidades. * pixeles La matriz de las intensidades. * * Devuelve una matriz de bytes con valores 0 o 1 (negro o blanco). */ char ** filtrar(int tmaster, int tant, int tsig, float tol, int tids[], int ntask, int alto, int ancho, float **pixeles) { int i, j, k, l, pasos, desde, hasta, filas, bufid; char **anterior = crearMatriz(alto, ancho), **actual = crearMatriz(alto, ancho), **temp; float M, s; bool hayCambios, hayArriba, hayAbajo; /* Cabezal int fsc = arr = aba = hc = nhc = cab; de los mensajes que se envian entre tareas */ FILA_SIN_CAMBIOS, FILA_DE_ARRIBA, FILA_DE_ABAJO, HAY_CAMBIOS, NO_HAY_CAMBIOS,

#ifdef DEBUG int mpasos, mk; #endif #ifdef MASTIEMPOS struct timeval *inicio, *fin, *total; inicio = new struct timeval; fin = new struct timeval; gettimeofday(inicio, NULL); #endif /* Bordes superior e inferior de la imagen original van en negro */ if (tant == -1) { for (j = 0; j < ancho; j++) { actual[0][j] = 0; } } if (tsig == -1) { for (j = 0; j < ancho; j++) { actual[alto - 1][j] = 0; } } /* Aplicamos primer filtro, dejar solo los bordes */ /* Se filtran solo las filas "1" a "alto - 2". Las filas "0" y "alto - 1" solo son * pasadas porque son necesarias para filtrar la siguientes filas.

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

26

Computacin de Alta Performance - 2001


*/ for (i = 1; i < alto - 1; i++) { for (j = 0; j < ancho; j++) { M = -FLT_MAX; for (l = 0; l < 8; l++) { s = aplicarMascara(pixeles, H[l], i, j); if (M < s) { M = s; } } M = fabs(M); if (M > tol) { actual[i][j] = 1; } else { actual[i][j] = 0; } } } #ifdef DEBUG cout << "Filtro de bordes pasado con xito...\n"; #endif #ifdef MASTIEMPOS gettimeofday(fin, NULL); total = difTiempo(fin, inicio); cout << "Tiempo utilizado para filtro de bordes: " << total->tv_sec << "." << total->tv_usec << "\n"; gettimeofday(inicio, NULL); #endif

Deteccin de Bordes y Afinado

/* Aplicamos el ltimo filtro, afinado de los bordes encontrados antes */ pasos = 0; hayCambios = true; /* Decido qu parte del fragmento le toca modificar a esta tarea * y cuntas filas debe recibir de parte de sus vecinos (0, 1 o 2). */ filas = 0; if (tant == -1) { desde = 0; } else { desde = 1; filas++; } if (tsig == -1) { hasta = alto; } else { hasta = alto - 1; filas++; } hayArriba = true; hayAbajo = true; #ifdef THINNING while (hayCambios) { pasos++; /* Aplico "estructurantes" a todos los puntos de la imagen */ hayCambios = false; for (k = 0; k < 8; k++) { /* Envio las filas que me toca modificar y que necesitan los dems */

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

27

Computacin de Alta Performance - 2001


if (tant != -1) {

Deteccin de Bordes y Afinado

#ifdef DEBUG if (hayArriba) { cout << "Enviando fila al anterior con cambios...\n"; } else { cout << "Indicando al anterior que no hay cambios...\n"; } #endif bufid = pvm_initsend(PvmDataDefault); if (hayArriba) { pvm_pkint(&aba, 1, 1); pvm_pkbyte(actual[1], ancho, 1); } else { pvm_pkint(&fsc, 1, 1); } if (pvm_send(tant, MSG_FILA) != 0) { pvm_perror("Error al enviar el mensaje a proceso de filtrado"); pvm_exit(); exit(1); } } if (tsig != -1) { #ifdef DEBUG if (hayAbajo) { cout << "Enviando fila al siguiente con cambios...\n"; } else { cout << "Indicando al siguiente que no hay cambios...\n"; } #endif bufid = pvm_initsend(PvmDataDefault); if (hayAbajo) { pvm_pkint(&arr, 1, 1); pvm_pkbyte(actual[alto - 2], ancho, 1); } else { pvm_pkint(&fsc, 1, 1); } if (pvm_send(tsig, MSG_FILA) != 0) { pvm_perror("Error al enviar el mensaje a proceso de filtrado"); pvm_exit(); exit(1); } } /* Recibo las filas que modificaron los otros y que necesito */ for (i = 0; i < filas; i++) { #ifdef DEBUG cout << "Esperando por fila de tarea adyacente...\n"; #endif bufid = pvm_recv(-1, MSG_FILA); pvm_upkint(&cab, 1, 1); switch (cab) { case FILA_DE_ARRIBA: pvm_upkbyte(actual[0], ancho, 1); #ifdef DEBUG cout << "Fila superior recibida...\n"; #endif break; case FILA_DE_ABAJO:

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

28

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

pvm_upkbyte(actual[alto - 1], ancho, 1); #ifdef DEBUG cout << "Fila inferior recibida...\n"; #endif break; #ifdef DEBUG case FILA_SIN_CAMBIOS: cout << "Fila sin cambios...\n"; #endif } pvm_freebuf(bufid); } #ifdef DEBUG cout << "Aplicando estructurante " << k + 1 << "\n"; #endif /* El thinning se aplica sobre la matriz "anterior" y escribe en "actual" */ temp = anterior; anterior = actual; actual = temp; hayArriba hayAbajo = false; = false;

for(i = desde; i < hasta; i++) { for(j = 0; j < ancho; j++) { if(aplicarThinning(anterior, actual, B[k], i, j, alto, ancho)) { hayCambios = true; /* Me recuerdo si hay cambios en los extremos */ if (!hayArriba && i == desde) { hayArriba = true; } if (!hayAbajo && i == hasta - 1) { hayAbajo = true; } } } } } #ifdef DEBUG cout << "Termin paso " << pasos << "...\n"; #endif if (tmaster != -1) { /* Comunico al "master" si hubieron o no cambios */ bufid = pvm_initsend(PvmDataDefault); if (hayCambios) { pvm_pkint(&hc, 1, 1); #ifdef DEBUG cout << "Tarea indicar a master que hay cambios\n"; #endif } else { pvm_pkint(&nhc, 1, 1); #ifdef DEBUG cout << "Tarea indicar a master que NO hay cambios\n"; #endif } if (pvm_send(tmaster, MSG_SEGUIR) != 0) { pvm_perror("Error al enviar notificacin a tarea \"master\"\n");

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

29

Computacin de Alta Performance - 2001


pvm_exit(); exit(1); }

Deteccin de Bordes y Afinado

/* Espero hasta que el "master" me diga si debo continuar */ bufid = pvm_recv(tmaster, MSG_SEGUIR); pvm_upkint(&cab, 1, 1); if (cab == HAY_CAMBIOS) { hayCambios = true; } #ifdef DEBUG if (cab == HAY_CAMBIOS) { cout << "Master indica que DEBEMOS CONTINUAR\n"; } else { cout << "Master indica que ya terminamos\n"; } #endif } else { if (ntask > 0) { /* Espero que restantes tareas indiquen si hay cambios */ for (i = 0; i < ntask; i++) { bufid = pvm_recv(-1, MSG_SEGUIR); pvm_upkint(&cab, 1, 1); #ifdef DEBUG if (cab == HAY_CAMBIOS) { cout << "Tarea notifica existencia de cambios\n"; } else { cout << "Tarea notifica que NO tiene ms cambios\n"; } #endif if (cab == HAY_CAMBIOS) { hayCambios = true; } } /* Indico a las tareas si deben seguir o mandar la informacin */ bufid = pvm_initsend(PvmDataDefault); if (hayCambios) { cab = HAY_CAMBIOS; } else { cab = NO_HAY_CAMBIOS; } pvm_pkint(&cab, 1, 1); if (pvm_mcast(tids, ntask, MSG_SEGUIR) != 0) { pvm_perror("Error en multicast a tareas\n"); pvm_exit(); exit(1); } } } #ifdef DEBUG cout << "Fin de paso " << pasos << "\n"; #endif } #endif #ifdef MASTIEMPOS gettimeofday(fin, NULL); total = difTiempo(fin, inicio); cout << "Tiempo utilizado para thinning: " << total->tv_sec << "." << total->tv_usec << "\n"; #endif return actual; }

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

30

Computacin de Alta Performance - 2001

Deteccin de Bordes y Afinado

/* El el filtrado se divide en los siguientes pasos: * * 1) Cargar una imagen a colores a memoria. Se obtiene una matriz con los * valores RGB de cada pixel. * * 2) Calcular la intensidad de la luz (o luminancia = nivel de gris) de * cada pixel obteniendo guardandolos en una matriz. * * 3) Filtrar la imagen (matriz de intensidades) utilizando compass * operators. El resultado del filtrado es una matriz binaria, donde un * 1 indica que el pixel pertenece a un borde (pixel con mximo gradiente) * y un 0 indica que el pixel no est en un borde. * * 4) Aplicar un algoritmo de thinning a los bordes para que los mismos sean de * un pixel de espesor. */ int main(int argc, char **argv) { int mitid, padre, i, j, k, l, ntask, *tids, tant, tsig, tmaster, pos, alto, ancho, canales, bufid, desde, hasta, fdesde, fhasta; float tol, **inten; char **res; char *input, *output, *fila; png_bytepp matriz, matrizSalida; png_structp ptr_png; png_infop ptr_info; // Manejo de pngs

struct timeval *inicio, *fin, *total, *inrecv, *finrecv; inicio = new struct timeval; fin = new struct timeval; total = new struct timeval; inrecv = new struct timeval; finrecv = new struct timeval; gettimeofday(inicio, NULL); /* Identificador de esta tarea en pvm */ mitid = pvm_mytid(); if (mitid < 0) { pvm_perror(argv[0]); exit(1); } /* Identificador de tarea padre */ padre = pvm_parent(); if (padre < 0 && padre != PvmNoParent) { pvm_perror(argv[0]); pvm_exit(); exit(1); } if (padre == PvmNoParent) { /* Si no tengo padre soy la tarea inicial */ int procs; struct timeval *inicio, *fin, *total; inicio = new struct timeval; fin = new struct timeval; total = new struct timeval; if (argc != 5 ) { cout << "Uso: " << argv[0] << " <entrada> <salida> <tolerancia> <procesos>\n"; pvm_exit(); exit(1);

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

31

Computacin de Alta Performance - 2001


} input = argv[1]; output = argv[2]; tol = atof(argv[3]); procs = atoi(argv[4]); if (procs <= 0) { cout << "El nmero mnimo de procesos permitido es 1\n"; pvm_exit(); exit(1); } /* Creamos las tareas "hijas" */ ntask = procs - 1; if (ntask > 0) { tids = new (int)[ntask];

Deteccin de Bordes y Afinado

if (pvm_spawn("hpc", NULL, 0, NULL, ntask, tids) != ntask) { pvm_perror("Error al crear las tareas \"hijas\"\n"); pvm_exit(); exit(1); } /* Enviamos a cada tarea la imagen que tienen que cargar, la * posicin que tienen asignada y cuales son sus tareas adyacentes. */ enviarDatos(input, tol, tids, ntask); tant = tids[ntask - 1]; } else { tant = -1; } tsig = -1; tmaster = -1; pos = ntask; } else { /* Es una tarea esclava, recibe los datos del master */ recibirDatos(pos, tant, tsig, ntask, input, tol); tmaster = padre; } /* Cargamos la imagen "input" en memoria */ cargarImagen(input, alto, ancho, canales, matriz, ptr_png, ptr_info); /* Cada tarea se queda con el fragmento que le corresponde */ dividirImagen(alto, ancho, canales, matriz, pos, ntask, fdesde, fhasta); /* Calculamos la intensidad de cada uno de los pxeles del fragmento */ inten = calcularIntensidades(alto, ancho, canales, matriz, fdesde, fhasta); /* Destruimos la imagen original para no ocupar tanta memoria */ png_destroy_read(ptr_png, ptr_info); /* Filtro del fragmento correspondiente */ res = filtrar(tmaster, tant, tsig, tol, tids, ntask, fhasta - fdesde, ancho, inten); if (padre == PvmNoParent) { /* Creamos la matriz para el resultado mientras van enviando los fragmentos */ matrizSalida = png_create_matrix( alto, ancho * 3); /* Paso matriz de 0s y 1s a RGB */ if (tant == -1) { desde = 0; }

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

32

Computacin de Alta Performance - 2001


else { desde = 1; } hasta = fhasta - fdesde; for (i = desde; i < hasta; i++) { for (j = 0; j < ancho; j++) { k = j * 3; if (res[i][j]) { matrizSalida[fdesde + i][k] = 255; matrizSalida[fdesde + i][k + 1] = 255; matrizSalida[fdesde + i][k + 2] = 255; } else { matrizSalida[fdesde + i][k] = 0; matrizSalida[fdesde + i][k + 1] = 0; matrizSalida[fdesde + i][k + 2] = 0; } } } /* Recibo los fragmentos siguientes */ if (ntask > 0) { gettimeofday(inrecv, NULL); fila = new char[ancho];

Deteccin de Bordes y Afinado

#ifdef DEBUG cout << "Recibiendo resultado de " << ntask << " tareas...\n"; #endif for (l = 0; l < ntask; l++) { bufid = pvm_recv(-1, MSG_RESULT); if (bufid < 0) { pvm_perror("Recibiendo resultado"); pvm_exit(); exit(1); } pvm_upkint(&desde, 1, 1); pvm_upkint(&hasta, 1, 1); #ifdef DEBUG cout << "Recibiendo fragmento (" << desde << ", " << hasta << ")...\n"; #endif for (i = desde; i < hasta; i++) { pvm_upkbyte(fila, ancho, 1); for (j = 0; j < ancho; j++) { k = j * 3; if (fila[j]) { matrizSalida[i][k] = 255; matrizSalida[i][k + 1] = 255; matrizSalida[i][k + 2] = 255; } else { matrizSalida[i][k] = 0; matrizSalida[i][k + 1] = 0; matrizSalida[i][k + 2] = 0; } } } pvm_freebuf(bufid);

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

33

Computacin de Alta Performance - 2001


}

Deteccin de Bordes y Afinado

gettimeofday(finrecv, NULL); total = difTiempo(finrecv, inrecv); cout << "Tiempo utilizado para recibir el resultado de los esclavos: " << total->tv_sec << "." << total->tv_usec << "\n"; } /* Guardamos el resultado en .png */ int error = png_write_file(output, ancho, alto, 8, matrizSalida); if (error) { cout << "Error al escribir la salida en " << output << "\n"; pvm_exit(); exit(1); } } else { /* Envio el resultado al "master" */ bufid = pvm_initsend(PvmDataDefault); hasta = fhasta - fdesde - 1; fhasta--; if (tant == -1) { desde = 0; } else { desde = 1; fdesde++; } #ifdef DEBUG cout << "Se envia fragmento (" << fdesde << ", " << fhasta << ") " << "de ancho " << ancho << "\n"; #endif pvm_pkint(&fdesde, 1, 1); pvm_pkint(&fhasta, 1, 1); for (i = desde; i < hasta; i++) { pvm_pkbyte(res[i], ancho, 1); } if (pvm_send(padre, MSG_RESULT) != 0) { pvm_perror("Enviando resultado a \"master\""); pvm_exit(); exit(1); } } /* Terminamos con PVM */ pvm_exit(); gettimeofday(fin, NULL); total = difTiempo(fin, inicio); cout << "Tiempo total: " << total->tv_sec << "." << total->tv_usec << "\n"; return 0; }

Juan Diego Ferr Enrico Pizzorno Nicols Sierra

34