C APÍTULO 5
D ISEÑO DE N ÚCLEOS H ARDWARE PARA EL P ROCESADO DE I MÁGENES
5.1. Introducción
Antes de comenzar con el diseño de núcleos hardware, se va a hacer una breve explicación de cómo se realiza el procesado de imágenes y qué tipo de herramientas se utilizan normalmente para llevar a cabo dicho proceso.
Principalmente, hay dos formas de realizar el procesado de imágenes, una a nivel de píxel y la otra a nivel local. A continuación se describen cada una de ellas:
Procesado a nivel de píxel: (también llamado procesado monopíxel [PFC_Navarro, 2000]). Ésta es una forma muy sencilla de procesar una imagen. Solamente es necesario conocer el valor de un píxel de la imagen a procesar, para obtener mediante algún tipo de cálculo su correspondiente píxel en la imagen procesada.
Procesado a nivel local:
(también llamado procesado multipíxel). A diferencia del procesado monopíxel, en esta forma de procesar un píxel es necesario conocer no sólo el valor de dicho píxel, sino que también se debe conocer el valor de los píxeles vecinos de su entorno.5.1.1. Procesado a nivel de píxel (Monopíxel)
Este tipo de procesado consiste en la transformación uno a uno de cada píxel que forma la imagen original, para obtener la imagen resultante. Si se considera la imagen original como p(x,y), la imagen resultante como q(x,y) y la función de transformación como un operador f, la relación matemática sería la siguiente:
q(x,y) = f ( p(x,y) )
La imagen original p(x,y) podría ser la siguiente, cada casilla corresponde con un valor entre 0 y 255, correspondiente a una escala de grises de 256 tonos de gris:
[Pajares, 2001] “La función de
transformación f puede ser un operador lineal o no lineal. El proceso matemático es relativamente simple. La imagen resultante es de la misma dimensión que la original.”. Dentro de estos operadores pueden estar el de identidad, el cual ofrece una imagen resultante idéntica a la imagen original; el inverso o negativo, que ofrece la imagen inversa a la de entrada; y entre muchos otros, está uno de los más utilizados que es el de umbral, con el que se obtiene una imagen resultante binaria a partir de una imagen en escala de grises. La función de transformación para este operador sería la siguiente:
Considerando el umbral como pl.
l l
p p
p q p
255 0
12 0 11
5 12 9 12
0 11 9 11
2 11 4 14
4 15 7 18
9 12
6 13 0 13
7 14 4 22
4 21 5 20
1 18 9 13
0 14 0 13
8 15 2 16
9 20 2 21
0 22 5 21
5 20 4 19
4 17 0 16
7 18 7 19
0 21 0 21
2 23 0 23
4 22 7 21
0 17 9 102 12
0 18 8 21
2 22 0 22
5 23 0 23
6 21 5 19
5 x
y Figura 5.1.
Ejemplo de una imagen de 5 filas
y 10 columnas
En el siguiente ejemplo la imagen original está formada por 5 filas y 10 columnas de píxeles cuyos valores están comprendidos entre 0 y 255 (8 bits sin signo 1 byte) en escala de grises, el resultado de aplicar un umbral de 200, da una imagen resultante en binario, es decir, con sólo dos valores posibles, siendo estos 0 y 255. El valor 0 corresponde al negro y el valor 255 al blanco. Por lo tanto, la imagen resultante estaría en blanco y negro.
Imagen original p(10,5) Imagen resultante q(10,5)
5.1.2. Procesado a nivel local (Multipíxel)
[Pajares, 2001] “Básicamente consiste en transformar el valor de un píxel p en al posición (x,y) teniendo en cuenta los valores de los píxeles vecinos”. Considerando los ocho vecinos de un cierto píxel en la posición (x,y), el píxel resultante en la misma posición será una suma ponderada con los valores de dichos vecinos. Los valores de ponderación se definen generalmente sobre una máscara con valores constantes. “Dicha máscara es realmente un filtro, por lo que dependiendo de la naturaleza del mismo así será el resultado final”.
Por ejemplo, si se considera la siguiente máscara,
9 8 7
6 5 4
3 2 1
m m m
m m m
m m m
el valor del píxel q(x,y) correspondería al resultado de la siguiente suma ponderada, cuyos factores de ponderación son los definidos en la máscara,
q(x,y) = m1 * p(x - 1, y - 1) + m2 * p(x, y - 1) + m3 * p(x + 1, y - 1) +
+ m4 * p(x - 1, y) + m5 * p(x, y) + m6 * p(x + 1, y) +
+ m7 * p(x - 1, y + 1) + m8 * p(x, y + 1) + m9
* p(x + 1, y + 1)
[Pajares, 2001] “realizando esta transformación sobre todos los píxeles de la imagen original con la misma máscara obtendremos una
00 0 00
0 00 0 00
0 00 0 00
0 00 0 00
0 00 0 00
0 00
0 00 0 00
0 00 0 25
5 25 5 25
5 00 0 00
0 00 0 00
0 00 0 00
0 25 5 25
5 25 5 25
5 25 5 00
0 00 0 00
0 00 0 00
0 25 5 25
5 25 5 25
5 25 5 25
5 00 0 00
0 00 0 00
0 25 5 25
5 25 5 25
5 25 5 25
5 00 0 12
0 11 5 12
9 12 0 11
9 11 2 11
4 14 4 15
7 18 9 12
6 13 0 13
7 14 4 22
4 21 5 20
1 18 9 13
0 14 0 13
8 15 2 16
9 20 2 21
0 22 5 21
5 20 4 19
4 17 0 167 18
7 19 0 21
0 21 2 23
0 23 4 22
7 21 0 17
9 102 12
0 18 8 21
2 22 0 22
5 23 0 23
6 21 5 19
5
f
215215 255255
Figura 5.2. Procesado monopíxel
nueva imagen de salida cuya dimensión es inferior a la original, ya que esta operación no se puede realizar sobre los píxeles extremos de la imagen original al no tener todos los vecinos 8”.
Antes de ver un ejemplo del procesado multipíxel, es conveniente explicar qué se quiere decir con eso de “vecinos 8”. Pues bien, hay dos conceptos de vecindad, entendiendo por vecindad al conjunto de los píxeles adyacentes a uno dado, está la vecindad a 4 y la vecindad a 8. Las figuras que se muestran a continuación dan una idea clara de este concepto.
Los cuadros sombreados son los 4 vecinos del píxel cuyo valor es 130.
Los cuadros sombreados son los 8 vecinos del píxel cuyo valor es 130.
A continuación, partiendo de la misma imagen que se utilizó para el apartado anterior, y la máscara M, se obtendría una imagen resultante de menores dimensiones, pero que en este caso, para mantener la correspondencia de píxeles, se han rellenado con ceros los píxeles que no tendrían correspondencia, estos son los píxeles que forman parte del borde de la imagen.
1 2 1
2 4 2
1 2 1 M 12
0 11 5 12
9 12
6 13 0 13
7 13
8 15 2 16
9
120 11 5 12
9 126 13
0 13 7 138 15
2 16 9
12 0 11
5 12 9 12
0 11 9 11
2 11 4 14
4 15 7 18
9 12
6 13 0 13
7 14 4 22
4 21 5 20
1 18 9 13
0 14 0 13
8 15 2 16
9 20 2 21
0 22 5 21
5 20 4 19
4 17 0 16
7 18 7 19
0 21 0 21
2 23 0 23
4 22 7 21
0 17 9 10
2 12 0 18
8 21 2 22
0 22 5 23
0 23 6 21
5 19 5
000 00 0 00
0 000 000 00 0 00
0 00
0 000 00 0 00
0 16 -7 - 163 17
9 -6 23 78 - 133 00
0 00
0 - 20 -
15 105 -87 31 -7 -
59 83 00 0 00
0 87 -
62 -5 -28 3 22 -6 15 00 0 00
0 00 0 00
0 000 000 00 0 00
0 00
0 000 00 0
Imagen original p(10,5) Imagen resultante q(10,5)
5.2. Descripción general de los núcleos hardware implementados
El diseño de núcleos hardware se ha realizado bajo el entorno de programación Foundation 2.1. de la empresa Xilinx. La programación se puede realizar mediante esquemáticos, diagramas de estado y lenguaje VHDL.
El núcleo será volcado en la FPGA que contiene la tarjeta Aristotle, cuyas características principales se detallan a continuación (más información en 4000.pdf, en la carpeta \documentos del CD):
XC4036EX-2
22.000 a 65.000 puertas de complejidad equivalente
1.296 CLBs (Bloques Lógicos Configurables) Matriz de 36 x 36 CLBs.
3.168 flip-flopsPara el correcto funcionamiento de los núcleos hardware en la tarjeta Aristotle se han de configurar correctamente ciertas señales que se encargan de la comunicación con las memorias FIFO de entrada y salida, las cuales se utilizan para enviar y recibir los datos por el bus PCI del host que contiene a la tarjeta.
Debido a que el bus PCI utiliza una frecuencia distinta a la que puedan llevar las FIFOs (ver apartado 4.4.2.3.), es necesario controlar cuándo las FIFOs están preparadas para enviar o recibir datos sin que éstas se desborden. Para ello, existen dos señales de aviso, también llamadas flags que cambian su estado lógico dependiendo de si las FIFOs están “casi llena” (almost full) o “casi vacía” (almost empty), según el caso.
Para el caso de la escritura en la FIFO de entrada desde el host, es necesario saber cuándo está “casi vacía”, para poder seguir cargándole datos. Mientras, si la FIFO de salida está “casi llena”, no se deben cargar datos hasta que el bus PCI descarge datos suficientes como para continuar con la transferencia. Estas señales están activas a nivel bajo, es decir, mientras estas señales estén a ‘1’, la transferencia será posible.
Las señales necesarias para realizar el control son:
Figura 5.3. Procesado multipíxel por máscara
AEB: Señal de “casi vacía” para la FIFO de entrada a la VPE (FPGA).
AFC: Señal de “casi llena” para la FIFO de salida al bus PCI.
RENB: Señal que habilita la posibilidad de lectura de la FIFO de entrada.
WENC: Señal que habilita la posibilidad de escritura de la FIFO de salida.
La idea lógica para el control de transferencia de datos, es la siguiente:
Como se puede observar en la figura la posibilidad de lectura y escritura de las FIFOs, sólo es posible mientras que las señales AEB y AFC estén desactivadas, es decir, estén a ‘1’.
Realmente el control de estas señales no es así exactamente, sino que ha de existir un retraso entre la señal de habilitación de lectura RENB y la de escritura WENC. Este retraso es debido al tiempo, o mejor dicho al número de ciclos de reloj, que tardan los datos en ser procesados.
5.2.1. Descripción modular de los algoritmos hardware.
El desarrollo de cada uno de los núcleos hardware se corresponde con una arquitectura hardware básica concreta. En esta arquitectura básica podemos distinguir módulos comunes a todos los núcleos hardware, siendo estos: un módulo de entrada, un módulo de salida, un módulo de control, módulo de configuración y un módulo de cálculo.
La Figura 5.5. muestra la composición modular básica de un núcleo hardware. Cada uno de los módulos está formado por
elementos hardware
concretos (p.e. flip-flops, puertas lógicas, etc), o entidades más complejas
RENB WENC AEB
AFC
“AND”
Núcleo Hardware
M.
E N T R A D A
M.
S A L I D A M.
CÁLCULO M. Control
M. Configuración Figura 5.4. Idea lógica del control de transferencia de datos
descritas en lenguajes de descripción hardware (HDL), tales como, VHDL.
La funcionalidad de cada uno de los módulos que componen un núcleo hardware se describe a continuación:
Módulo de entrada. Este módulo es el encargado de establecer el nexo de unión entre la FIFO de entrada y la FPGA.
Módulo de control. Controla y habilita la comunicación entre los núcleos hardware que configuran la FPGA y las FIFOs de comunicación.
Módulo de configuración. El módulo de configuración lleva a cabo la parametrización hardware de la unidad reconfigurable.
Esta configuración hardware debe realizarse desde el interior del núcleo. Entre las funciones parametrizables podemos destacar: ruteo de los relojes de la lógica secuencial, LED de comprobación, tamaño de los buses de entrada/salida (8- 16bits), direccionamientos de los bancos RAMs, etc.
Módulo de cálculo. Es el núcleo de cálculo del algoritmo. Realiza las operaciones aritméticas sobre los datos registrados por el módulo de entrada (sumas, multiplicaciones, divisiones, etc.).
Una vez los datos son procesados, estos son enviados al módulo de salida.
Módulo de salida. Es una unidad de registro, cuya misión es transferir los resultados del procesado al elemento hardware de comunicación (FIFO) con el bus PCI del host.
Los diferentes módulos mencionados anteriormente constituyen la composición mínima que debe tener un núcleo hardware. Los módulos estarán disponibles en librerías para su fácil integración en los nuevos diseños. Cada módulo estará compuesto por entidades de código de más bajo nivel, generadas por herramientas de diseño.
Estas herramientas permiten generar módulos en lenguajes de descripción hardware, esquemáticos o diagramas de estados finitos (FSM).
Atendiendo a la naturaleza del tratamiento de los datos de una imagen, por parte de un algoritmo concreto, se puede dividir los algoritmos en dos grupos:
Algoritmos de procesado monopíxel, cuando los datos de la imagen son tratados de manera aislada por el módulo de cálculo del núcleo hardware, es decir, las transformaciones sobre la información inicial de la imagen se realiza píxel a píxel,
perteneciendo a este grupo el algoritmo de binarización, cálculo de área, etc.
Algoritmos de procesado multipíxel son aquellos en los que el módulo de cálculo actúa de una forma ordenada sobre grupos de píxeles de una imagen, por ejemplo, cuatro o nueve píxeles.
En este grupo tenemos filtros espaciales, realces, detección de bordes, etc.
Antes de proceder a la descripción de los módulos que forman el diseño de los núcleos hardware, es importante explicar la simbología que se utiliza en la herramienta de diseño:
Por ejemplo, para los puertos de entrada y salida de la FPGA se utilizan los denominados IPAD y OPAD, respectivamente. Los símbolos utilizados son los siguientes:
Puerto de entrada
Puerto de salida
Otros elementos importantes a destacar son los buffers de entrada y salida, o los registros de entrada y salida, cuya simbología se muestra a continuación:
Buffer de entrada
Buffer de salida
Registro de entrada
Registro de salida
Puerto de jerarquía
A continuación, se describirán los distintos módulos que forman el diseño de los núcleos hardware.
5.2.1.1. Descripción del módulo de entrada y del módulo de salida.
El módulo de entrada está formado por el puerto donde se recogen los datos que vienen de la FIFO de entrada. Este puerto está constituido por un bus de 16 líneas conectadas a la dicha FIFO. El nombre de este bus es FID[15:0], para una configuración de 8 líneas de entrada se toman las 8 líneas menos significativas de ese bus, es decir, FID[7:0].
Dentro de la FPGA, el bus FID[15:0] o FID[7:0] se tiene que conectar a un registro de entrada tipo IFD16 o IFD8. En la figura siguiente se puede observar cómo sería esto:
Figura 5.6. Módulo de entrada.
El módulo de salida está formado por el puerto donde se colocan los datos para ser enviados a la FIFO de salida. Este puerto está constituido por un bus de 16 líneas conectadas a dicha FIFO. El nombre de este bus es FOD[15:0], para una configuración de 8 líneas de salida se toman las 8 líneas menos significativas de ese bus, es decir, FOD[7:0].
Dentro de la FPGA, el bus FOD[15:0] o FOD[7:0] se tiene que conectar a un registro de salida tipo OFD16 o OFD8. En la figura siguiente se puede observar cómo sería esto:
5.2.1.2. Descripción del módulo de control de comunicación El módulo de control como se explicó anteriormente, es el encargado de establecer una correcta comunicación entre las memorias FIFO y la FPGA, para la transferencia de
datos a través del bus PCI.
La Figura 5.8. muestra el símbolo del módulo de control
de comunicación
(M_CTRL_COM).
El módulo de control y comunicación posee tres entradas y tres salidas. La descripción de las entradas y las salidas se muestra en la Tabla 5.1.
Entradas/Salidas: Macro 1: Módulo de Control de Comunicación
Entradas Descripción
CLK Señal de reloj
AFC Flag de entrada FIFO “Casi lleno” activo a nivel bajo AEB Flag de entrada FIFO “Casi vacío” activo a nivel bajo Salidas
RENB Señal habilita lectura activa a nivel alto. Actualiza los contenidos FIFO durante la lectura
WENC Señal habilita escritura activa a nivel alto. Actualiza los contenidos FIFO durante la escritura.
Figura 5.7. Módulo de salida.
Figura 5.8. Símbolo del módulo M_CTRL_COM.
EN_WENC Señal habilita escritura para uso interno de la FPGA, activa a nivel alto. Habilita el módulo de cálculo.
5.2.1.2.1. Componentes del módulo de control de comunicación.
La Figura 5.14. muestra la arquitectura hardware del módulo de control de comunicación. El módulo está compuesto por lógica secuencial y combinacional.
El módulo posee las siguientes entidades hardware:
Elementos de enlace con las estructuras de orden jerárquico superior. Estos elementos pueden ser de salida
o de entrada, ver Figura 5.9.
Una puerta AND2 de dos entradas según Figura 5.10.
Dos registros de entrada y dos de salida de 1 bit. Los registros de entrada y los de salida se corresponden con flip-flops tipo D según la Figura 5.11.
Tabla 5.1. Entradas y salidas del módulo de control de comunicación.
Figura 5.11. Registros de entrada (IFD) y de salida (OFD).
Figura 5.9. Salidas y entradas jerárquicas.
Figura 5.10. Puerta AND de dos entradas.
Una FIFO reconfigurable de un bit que se utiliza para retrasar la escritura sobre la FIFO de salida, tantos ciclos de reloj como sean necesarios para el cálculo del primer dato válido. Este módulo tiene también una entrada de habilitación (enable). Ver Figura 5.12.
El código VHDL que ha sido implementado en este módulo se muestra en la Figura 5.13.
Descripción del funcionamiento del módulo de control de comunicación.
El módulo inicia la lectura siempre que el buffer bidireccional de entrada FIFO_IN no esté casi vacío (AEB) y el buffer bidireccional de salida FIFO_OUT no esté casi lleno (AFC).
La actualización de los registros FIFO durante la lectura y la escritura se realiza activando la señal de RENB y WENC durante un flanco ascendente de la señal de reloj.
Figura 5.12. FIFO reconfigurable de un bit.
Figura 5.13. FIFO reconfigurable de un bit.
El módulo de comunicación mostrado en la Figura 5.14., varios ciclos después (los configurados en la FIFO reconfigurable) de la lectura de un dato de la FIFO_IN escribe un dato en la FIFO_OUT.
5.2.1.3. Descripción del módulo de configuración
El acceso de los núcleos a los elementos hardware de la tarjeta reconfigurable, tales como, bancos SRAMs, FIFOs, LED, etc., implica una configuración previa de la unidad de diseño. Con este propósito se configuran los elementos hardware con valores predeterminados que permiten realizar las operaciones demandadas.
Los valores asignados a los elementos hardware pueden ser simples conexiones físicas de los elementos externos con pines de la FPGA, como es el caso de las señales de reloj (FIFO_CLK CLK), o asignaciones de valores lógicos estándar. Los valores lógicos asignados dependerán de la tecnología en la que se ubique el núcleo.
En el presente proyecto y para la FPGA XC4036EX de Xilinx los valores lógicos asignados a los elementos hardware son Vcc ‘1’= +5v y GND
‘0’= 0v.
Para la implementación de los diferentes algoritmos de visión en las distintas arquitecturas propuestas ha sido necesario establecer diferentes configuraciones hardware de la VPE (Virtual Processing Element), en concreto han sido implementadas dos configuraciones hardware diferentes.
5.2.1.3.1. Módulo M_conf_8/8/SR.
El módulo M_conf_8/8/SR de configuración hardware habilita un bus de 8 entradas y 8 salidas sin memoria RAM. Este módulo ha sido
Figura 5.14. Arquitectura del módulo de control de comunicación.
desarrollado para su integración en los diseños de los algoritmos de binarización y de detección de bordes.
La Tabla 5.2. muestra una descripción de cada uno de los elementos de entrada salida del módulo de configuración hardware M_conf_8/8/SR.
Entradas/Salidas del módulo M_conf_8/8/SR de configuración hardware.
Entradas Valor Descripción
FIFO_CLK Ruta Señal de reloj
Salidas
SIZEB Vcc Fija el bus FID de entrada a 8 bits.
CSB GND Activa los controladores de salida de datos FIFO.
MBB GND Selecciona el registro de salida durante la lectura de la FIFO.
SIZEC Vcc Fija el bus FOD de salida a 8 bits.
LED GND Pone a OFF el LED de la VPE.
MBC GND Selecciona el registro de salida durante la escritura de la FIFO.
Tabla 5.2. Funcionalidad de los elementos del módulo M_conf_8/8/SR.
Figura 5.15. Módulo de configuración hardware M_conf_8/8/SR.
5.2.1.3.2. Módulo M_conf_8/16/SR.
El módulo de configuración hardware M_conf_8/16/SR habilita un bus de 8 entradas y 16 salidas sin memoria RAM. Este módulo ha sido integrado en el diseño del algoritmo de cálculo de área.
La Tabla 5.3. muestra una descripción de cada uno de los elementos de entrada salida del Módulo de configuración hardware M_conf_8/8/SR.
Entradas/Salidas del módulo M_conf_8/16/SR de configuración hardware.
Entradas Valor Descripción
FIFO_CLK Ruta Señal de reloj
VPE_RESET Ruta Señal de reset
Salidas
SIZEB Vcc Fija el bus FID de entrada a 8 bits.
CSB GND Activa los controladores de salida de datos FIFO.
MBB GND Selecciona el registro de salida durante la lectura de la FIFO.
SIZEC GND Fija el bus FOD de salida a 16 bits.
LED GND Pone a OFF el LED de la VPE.
MBC GND Selecciona el registro de salida durante la escritura de la FIFO.
5.2.1.4. Descripción del los algoritmos de cálculo
Figura 5.16. Módulo de configuración hardware M_conf_8/16/SR.
Tabla 5.3. Funcionalidad de los elementos del módulo M_conf_8/16/SR.
Como ya se ha visto anteriormente, hay dos tipos de procesado que se van a implantar en este proyecto, el monopíxel y el multipíxel. A continuación se describe cómo sería el algoritmo para cada uno.
5.3. Núcleos HW de procesado monopíxel
Para este proyecto fin de carrera se ha implementado dos algoritmos de procesado monopíxel: uno para el cálculo de la imagen binaria por comparación de umbral y otro para el cálculo del área de una imagen binaria.
Algoritmo de binarización
El cálculo de la imagen binaria se ha realizado por comparación de umbral. Por ejemplo, para un umbral en 200, se sigue la siguiente lógica:
200 255
200 0
p q p
Considerando a q como el dato de salida y a p como el dato de entrada. Claro está que cada dato corresponde con un píxel de la imagen correspondiente.
En la Figura 5.17. se muestra el módulo BINARIZA donde se ha implementado el cálculo por comparación de umbral.
Este proceso de cálculo se llama binarización y está implementado en lenguaje VHDL, siendo la sintaxis, la que se muestra a continuación:
Figura 5.17. Símbolo del módulo de comparación de umbral.
Según el código anterior, la señal PIN[7:0] corresponde con el dato de entrada y la señal POUT corresponde con el dato de salida.
En la línea 16 se fija el valor de umbral de binarización. Este valor expresado en base binaria “11001000b” corresponde con el “200d”
en base decimal. La modificación del umbral se consigue sustituyendo este valor binario por el valor con el que se desee comparar.
La tabla 5.4. muestra las entradas y salidas del módulo de comparación de umbral.
Entradas/Salidas: Módulo de comparación de umbral
Entradas Descripción
PIN[7:0] Bus de 8 bits que contiene el dato a binarizar
Salidas
POUT[7:0]
Bus de 8 bits que contiene el dato binarizado
Algoritmo de área
El cálculo del área de una imagen binaria consiste en contar el número de píxeles que tiene un objeto dentro de una imagen. Se
Figura 5.18. Código VHDL del módulo de comparación de umbral.
Tabla 5.4. Entradas y salidas del módulo de comparación de umbral.
considera que un objeto está formado por los píxeles cuyo valor es 255 (blanco) y los píxeles con valor 0 (negro) forman el fondo de la imagen. En la Figura 5.19. se muestra el símbolo del módulo CALC_AREA para el cálculo del área:
Este módulo se ha implementado en VHDL, cuya sintaxis se muestra en la Figura 5.20.
La tabla 5.4. muestra las entradas y salidas del módulo de comparación de umbral.
Figura 5.19. Símbolo del módulo de cálculo de área.
Figura 5.20. Código VHDL del módulo CALC_AREA.
5.4. Núcleos HW de procesado multipíxel
Como algoritmo de procesado multipíxel se ha optado por un procesado por filas, donde se realiza la convolución de la imagen a procesar con una máscara 3x3. El tipo de máscara a utilizar es una máscara de Laplace que tiene como objeto la determinación de los puntos en que se produce una variación de intensidad. Los métodos de detección de bordes se basan en los operadores derivada. La Figura 5.21. analiza como se modifica la intensidad de la imagen
al sufrir
una
derivada primera y segunda.
-113-
Entradas/Salidas: Módulo cálculo de área
Entradas Descripción
DIN[7:0] Bus de 8 bits que contiene el dato de entrada
ENABLE[7:0] Señal para la habilitación del módulo CLK[7:0] Señal de reloj
Salidas
DOUT[7:0]
Bus de 8 bits que contiene el área contada
Tabla 5.5. Entradas y salidas del módulo de cálculo de área CALC_AREA.
El operador Laplaciana tiene la siguiente estructura matemática:
( , ) 22 22
y f x
y f x f
L
Dos de las máscaras más típicas que se utilizan como operadores de Laplace son las siguientes:
(a) (b)
Módulo de entrada
En la estructura de la Figura 5.23. se puede observar que el módulo de entrada está formado por el bus de entrada Píxel_IN, nueve elementos básicos de registro y dos registros FIFO. Como lo que se pretende es procesar una imagen de MxN (M filas y N columnas) con datos de 8 bits, los registros utilizados son también de 8 bits. Los nueve elementos básicos de registro se utilizan para almacenar los datos que van a estar presentes en la convolución con la máscara de procesado. Los registros FIFO se utilizan para almacenar N – 3 datos, en cada uno. Estos son el resto de los datos que forman las filas de la imagen. Conforme van entrando datos, se va recorriendo la imagen de izquierda a derecha y de arriba hacia abajo.
La Figura 5.23. muestra una idea de cómo sería la estructura propuesta para el procesado por filas.
-114-
-1 -1 -1
-1 8 -1
-1 -1 -1
0 -1 0
-1 4 -1
0 -1 0
Figura 5.22. Máscaras de Laplace.
Registro FIFO
fila i
fila i+1 fila i- 1
Módulo de procesad
o 3x3 Módulo de
procesado
Píxel_OUT
Módulo de salida
Píxel_
IN
Registro FIFO
Módulo de entrada
Módulo de configura
ción Módulo
de comunica
ción
Registros FIFO
El objetivo de los registros FIFO es almacenar los datos correspondientes al tamaño de la fila, menos los tres datos de esa fila que van a ser procesados. Por ejemplo, si se está trabajando con imágenes de 5 filas y 10 columnas, entonces el tamaño de los registros FIFO es de 10–3= 7. En general, para una imagen MxN (M filas y N columnas), el tamaño de los registros FIFO es de N – 3.
Los registros FIFO son implementados en la FPGA, esto no supone ningún problema cuando se trabaje con imágenes pequeñas, pero sí cuando las imágenes alcanzan un tamaño (varía según el tipo de FPGA), debido a que las FPGAs tienen limitada
su capacidad. Para imágenes grandes debe usarse una memoria externa.
El módulo utilizado para este diseño sería el de la Figura 5.24.
Entradas/Salidas: Módulo de FIFO_CONF Figura 5.24. Módulo
FIFO_CONF.
Entradas Descripción
SIN[7:0] Bus de 8 bits por donde entran los datos uno a uno
ENABLE Habilita el módulo FIFO_CONF CLK Reloj de sincronización
Salidas
SOUT[7:0]
Bus de 8 bits por donde salen los datos un tiempo determinado después de haber entrado
Este módulo ha sido implementado en código VHDL, la Figura 5.25.
muestra la sintaxis del mismo:
En la línea 12 del código se configura el tamaño del registro, en este caso es 97, considerando que la imagen de entrada tiene un ancho de 100 píxeles.
Tabla 5.6. Entradas/Salidas del módulo FIFO_CONF.
Figura 5.25. Código VHDL del módulo FIFO_CONF.
Considerando la imagen de entrada la de la Figura 5.26., los datos irían entrando uno a uno en el módulo de entrada, es decir, primero entraría el dato 120, en el siguiente flanco de reloj entraría el 115, después el 129, seguido del 120 y así hasta el último dato de la imagen.
En la siguiente figura se muestra los valores correspondientes a la imagen de entrada. Los cuadros sombreados corresponden con los datos de la primera máscara que será procesada correctamente por el módulo de cálculo.
En la Figura 5.27. se muestra el
recorrido de los datos de entrada
dentro del núcleo de procesado
hardware.
En el siguiente flanco de reloj al instante del ejemplo anterior los datos de la imagen de entrada para ser procesados son los cuadros sombreados que aparecen en la Figura 5.28.:
-117- 12
0 11 5 12
9 12 0 11
9 11 2 11
4 14 4 15
7 18 9 12
6 13 0 13
7 14 4 22
4 21 5 20
1 18 9 13
0 14 0 13
8 15 2 16
9 20 2 21
0 22 5 21
5 20 4 19
4 17 0 16
7 18 7 19
0 21 0 21
2 23 0 23
4 22 7 21
0 17 9 10
2 12 0 18
8 21 2 22
0 22 5 23
0 23 6 21
5 19 5
12 0 11
5 12 9 12
0 11 9 11
2 11 4 14
4 15 7 18
9 126 13
0 13 7 14
4 22 4 21
5 20 1 18
9 13 0 14
0 138 15
2 16 9 20
2 21 0 22
5 21 5 20
4 19 4 17
0 16 18 19 21 21 23 23 22 21 17
202 169 152 138
137 130 126
129 115 120
140...144
189...120 Píxel_
IN
Datos para ser procesados
Figura 5.26. Imagen ejemplo de entrada.
Figura 5.27. Recorrido de los datos a través del módulo de entrada.
Los registros de datos quedarían de la siguiente forma:
Módulo de detección de bordes para una imagen binaria
El cálculo de los datos de salida para este tipo de procesamiento, se realiza como ya se dijo anteriormente, mediante una convolución entre los datos de entrada y la máscara seleccionada para dicho proceso. Para este proyecto se han seleccionado dos máscaras típicas de Laplace cuyos valores se muestran en las figuras a y b de la Figura 5.22. El medio que se ha utilizado para realizar la convolución es mediante lenguaje VHDL. Para cada una de las máscaras se ha realizado un módulo diferente.
La imagen de entrada es binaria, es decir, sólo tiene dos valores posibles que son 0 para los píxeles en negro y 255 para los píxeles en blanco. El utilizar una imagen binaria simplifica el cálculo de los píxeles que forman el borde del objeto en cuestión. Como se verá en el apartado siguiente, no es necesario que la imagen original sea binarizada antes de enviarla a la FPGA, sino que esta es capaz de incorporar varios procesos en serie. Por ejemplo, para este caso, el procesado monopíxel que se vio en el apartado anterior, sería conveniente colocarlo antes del procesado multipíxel, para tener directamente la imagen binaria necesaria.
A continuación, se muestra cada uno de los módulos utilizados para las dos máscaras:
Píxel_
IN
210 202 169 152
144 137 130
120 129 115
138...224
126...119
Datos para ser procesados
Figura 5.28. Imagen ejemplo de entrada.
Figura 5.29. Recorrido de los datos a través del módulo de entrada.
El módulo CALCMASC está formado por 9 buses de entrada y un bus de salida. Los 9 buses de entrada son los 9 datos que van a ser procesados por la máscara de la Figura 5.22a.
Entradas/Salidas: Módulo CALMASC
Entradas Descripción
P1I[7:0] Bus de 8 bits que contiene el dato (i-1,j- 1)
P1J[7:0] Bus de 8 bits que contiene el dato (i,j-1) P1K[7:0] Bus de 8 bits que contiene el dato
(i+1,j-1)
P2I[7:0] Bus de 8 bits que contiene el dato (i-1,j) P2J[7:0] Bus de 8 bits que contiene el dato (i,j) P2K[7:0] Bus de 8 bits que contiene el dato
(i+1,j)
P3I[7:0] Bus de 8 bits que contiene el dato (i- 1,j+1)
P3J[7:0] Bus de 8 bits que contiene el dato (i,j+1)
P3K[7:0] Bus de 8 bits que contiene el dato (i+1,j+1)
Salidas
RESULTADO[7:0] Bus de 8 bits que contiene el dato (i,j) de la imagen resultante
En la Figura 5.31. se muestra una idea de la operación que realiza el módulo CALCMASC.
… … …
… q(i,j
) …
… … …
p(i-1,j- 1)
p(i,j- 1)
p(I+1,j -1) p(i-
1,j) p(i,j) p(I+1,j) p(i-
1,j+1) p(i,j +1)
p(I+1,j +1)
Figura 5.30. Módulo de cálculo CALMASC
Tabla 5.7. Entradas/Salidas del módulo de cálculo CALMASC
Módulo CALCMASC
Imagen de entrada Imagen de salida
Las señales M1I, M1J, M1K, etc. son los correspondientes valores que forman la máscara con la que se realizará la convolución. La forma que tendría la máscara sería la siguiente:
El código en VHDL que contiene el módulo de cálculo sería este:
M1I M1J M1
K
M2I M2J M2
K
M3I M3J M3
K
Figura 5.32. Código VHDL del módulo CALMASC
Obsérvese que en la línea 41 del código el resultado es 11111111b (255 en decimal) cuando auxA < auxB y en otro caso es 00000000b (0 en decimal). La señal auxB es el resultado de la multiplicación entre el píxel (i,j) de la imagen de entrada y M2J, mientras que la señal auxA es la suma de las multiplicaciones entre los píxeles de entrada restantes y los valores de la máscara correspondientes.
Cuando auxA < auxB el resultado de la convolución sería positivo, por lo que el píxel (i,j) de la imagen resultante pertenecería al borde del objeto.
El módulo CALCMASC_4 está formado por 5 bus de entrada y un bus de salida. Los 5 bus de entrada son los 5 datos que van a ser procesados por la máscara de la Figura 5.22b.
-121-
Entradas/Salidas: Módulo CALMASC_4
Entradas Descripción
P1J[7:0] Bus de 8 bits que contiene el dato (i,j-1) P2I[7:0] Bus de 8 bits que contiene el dato (i-1,j) P2J[7:0] Bus de 8 bits que contiene el dato (i,j) P2K[7:0] Bus de 8 bits que contiene el dato
(i+1,j)
P3J[7:0] Bus de 8 bits que contiene el dato (i,j+1)
CLK Señal de reloj del sistema
Salidas
Figura 5.33. Módulo de cálculo CALMASC_4
En la Figura 5.34. se muestra una idea de la operación que realiza el módulo CALCMASC_4.
El código en VHDL que contiene el módulo de cálculo sería este:
… p(i,j-
1) …
p(i-
1,j) p(i,j) p(I+1,j)
… p(i,j
+1) …
… … …
… q(i,j
) …
… … …
Figura 5.34. Representación gráfica del módulo de cálculo CALMASC_4
Módulo CALCMASC_4
Imagen de entrada Imagen de salida
Tabla 5.8. Entradas/Salidas del módulo de cálculo CALMASC_4
Figura 5.35. Código VHDL del módulo CALMASC_4
Módulo de procesado 3x3
Para mayor comodidad en el diseño núcleos hardware, el algoritmo de procesado multipíxel ha sido implementado en un modulo (DETEC_PERIM) cuyo símbolo se muestra en la Figura 5.36.
Este módulo utiliza el módulo CALCMASC_4 para el cálculo del perímetro. La tabla 5.9. muestra las entradas y salidas de este módulo.
Entradas/Salidas: Módulo DETEC_PERIM
Entradas Descripción
P_TK[7:0] Bus de 8 bits de los datos de entrada CLK Señal de reloj del sistema
Salidas
RESULTADO[7:0] Bus de 8 bits que contiene el dato (i,j) de la imagen resultante
Figura 5.36. Módulo de procesado 3x3 DETEC_PERIM
Tabl 5.9. Módulo de procesado 3x3 DETEC_PERIM
La Figura 5.37. muestra el esquemático que ha sido implementado en el módulo DETEC_PERIM.
5.5. Ejemplos de aplicación
Dentro de las posibilidades que ofrece una FPGA está el poder trabajar con distintos módulos de procesado en cadena (pipeline), esto quiere decir, que mientras se está llevando a cabo el procesamiento de un píxel o varios, se puede realizar al mismo tiempo el procesamiento de otros.
Con la ayuda de una amplia librería de módulos de procesado, la configuración de algoritmos pipeline se hace muy sencilla, sólo basta con tomar los módulos necesarios y conectarlos entre sí.
Una vez se ha hecho la configuración, se tienen que generar los núcleos hardware que se utilizarán para la programación de una
Figura 5.37. Esquema del módulo de procesado 3x3 DETEC_PERIM
FPGA. Estos núcleos hardware son generados mediante la misma herramienta de diseño (Foundation 2.1), obteniendo un archivo bitstream con la extensión .BIT, que será utilizado para dicha programación.
Para este proyecto fin de carrera se han propuesto dos algoritmos pipeline: uno realiza la detección de bordes dentro de una imagen y el otro realiza el cálculo del perímetro de un objeto dentro de una imagen. Estos algoritmos son PRXFIL y PERIM, respectivamente. A continuación se presentan cada uno de estos algoritmos:
5.5.1. Algoritmo para detección de bordes (PRXFIL)
Para realizar la detección de bordes dentro de una imagen en escala de grises, se han tomado dos módulos explicados anteriormente, el módulo de binarización BINARIZA y el módulo de detección de bordes de Laplace DETEC_PERIM. La configuración del algoritmo se presenta en la Figura 5.38.
Este algoritmo ha sido implementado para generar un núcleo hardware con el nombre PRXFIL.BIT, con el que se realizará la programación de una FPGA.
En la tabla 5.10. se muestran los datos obtenidos en la implementación del núcleo hardware, viéndose en ella qué tanto por ciento de ocupación se ha obtenido sobre la FPGA.
Figura 5.38. Esquema del núcleo PRXFIL
5.5.2. Algoritmo para cálculo del perímetro (PERIM)
Para realizar el cálculo del perímetro de un objeto dentro de una imagen en escala de grises, se han tomado tres módulos explicados anteriormente, el módulo de binarización BINARIZA, el módulo de detección de bordes de Laplace DETEC_PERIM y el módulo del cálculo del área CALC_AREA. La configuración del algoritmo se presenta el la Figura 5.39.
Con este algoritmo se ha generado el núcleo PERIM.BIT con el que se realizará la programación de una FPGA.
En la tabla 5.11. se muestran los datos obtenidos en la implementación del núcleo hardware, viéndose en ella qué tanto por ciento de ocupación se ha obtenido sobre la FPGA.
-127-
Núcleo PRXFIL %
Número de IOBs externas 8
Número de IOBs de buffer global 12
Número de CLBs: 71
Total latches 0 Total CLBs
flops
70 LUTs de 4
entradas
1 LUTs de 3
entradas 69
Número BUFGLSs 12
Núcleo PERIM %
Número de IOBs externas 12
Número de IOBs de buffer global 12
Número de CLBs: 72
Total latches 0 Total CLBs
flops 70
LUTs de 4 entradas
1 LUTs de 3 69 Figura 5.39. Esquema del núcleo PERIM Tabla 5.10. Resumen de ocupación para núcleo PRXFIL
Tabla 5.11. Resumen de ocupación para núcleo PERIM