Python vs Verilog: Procesamiento de Imagenes en tiempo real

Python: Un Vistazo Inicial

Python, un lenguaje de programación tan versátil como popular, ha ganado terreno en el mundo del desarrollo de software gracias a su facilidad de aprendizaje y su amplia gama de aplicaciones. En el ámbito del procesamiento de imágenes, no es una excepción. Desde la aplicación de filtros hasta tareas más complejas, Python ofrece múltiples enfoques, ya sea a través de bibliotecas especializadas como OpenCV o mediante el desarrollo de soluciones «desde cero» utilizando sus capacidades nativas. Sin embargo, al comparar Python con otras herramientas, como Verilog, para el procesamiento de imágenes, es crucial entender las diferencias fundamentales en cómo cada una aborda esta tarea. En este artículo, exploraremos estas diferencias y sus implicaciones para aquellos interesados en sistemas digitales y procesamiento de imágenes.

Lenguajes de programacion mas utilizados en repositorios de GitHub

Es importante señalar que esta comparativa entre Python y Verilog para el procesamiento de imágenes puede parecer injusta en ciertos aspectos. Cuando aplicamos un filtro de imágenes con Python, estamos esencialmente ejecutando código de software en la CPU de nuestro sistema. Cada operación, desde la lectura de la imagen hasta la aplicación del filtro y la escritura del resultado, se traduce en instrucciones que deben ser ejecutadas secuencialmente. Este enfoque puede resultar en un cuello de botella significativo, ya que estamos limitados por la velocidad de procesamiento de la CPU.

Aunque Python ofrece la posibilidad de utilizar técnicas de multiprocesamiento para mejorar el rendimiento, para efectos de esta comparativa nos centraremos en un enfoque más básico, utilizando bucles for para iterar sobre los píxeles de la imagen. Este método, si bien funcional, puede no ser la opción más eficiente en términos de rendimiento, especificamente en este articulo es conveniente realizarlo de esta forma para resaltar las diferencias que existen en ejecucion de software y simulacion del hardware.


Verilog: Implementacion de un hardware que procesa imagenes

Comunmente estamos acostumbrados a realizar diseños de circuitos digitales que son alimentadas con señales binarias que nos arrojaran ‘1’ o ‘0’ dependiendo de lo que querramos. En nuestras primeras clases de diseño digital aprendemos a diseñar, un multiplexor 2 a 1, un sumador completo, etc. Sin embargo, puede suceder el caso que no tengamos la mas minima idea de ¿Como se carga una imagen en un circuito digital? pues esta duda la podemos resolver ahora mismo!

Dentro del diseño de circuitos digitales existen muchas etapas importantisimas para que todo salga bien al finalizar el producto que es el chip.

Sin embargo en este articulo queremos enfocarnos en 2:

  • La simulacion del hardware
  • La sintesis del hardware

Durante la simulacion, dependiendo del lenguaje que utilizemos para diseñar hardware, tendremos palabras reservadas para la carga de archivos y que el simulador que estemos utilizando reconozca el archivo y de esta forma pueda utilizarlo para cargar señales de 1’s y 0’s a una pieza de hardware. Este tipo de archivos durante simulacion pueden ser almacenados en una memoria de nuestro testbench. En el caso de Verilog estas palabras reservadas serían $readmemb y $readmemh los cuales toman como entrada el archivo que debe estar en algun formato de datos binario como por ejemplo, .hex, .mem, .mif, etc. o inclusive un txt de toda la vida. Estos archivos comunmente van a describirnos datos binarios y como son almacenados en un espacio de memoria.

Bueno, pero estos formatos binarios que tienen que ver con la carga de una imagen ? Pues resulta que podemos generar estos archivos a mano o mediante software, para nuestro pequeño ejemplo, hemos generado estos archivos con Python mismo ya que es un lenguaje bastante practico. Simplemente leemos la informacion de cada pixel y lo escribimos como un texto plano dentro de nuestro archivo .mem. Por ejemplo: Un pixel de nuestra imagen puede tener el color Rojo: El cual significa que si consideramos que tiene 24 bits de color y un espacio de colores en RGB, se ocupan 8 bits por cada color de la siguiente forma:

Representacion de un espacio de memoria de 24 bits que ocupa un pixel

Como nuestro pixel es rojo seguramente tengamos el valor de : 11111111 00000000 00000000

Para un pixel amarillo se requiere la combinacion de Rojo y Verde: 11111111 11111111 00000000

En nuestro archivo txt o mem se escribiran estos datos separados linea por linea, lo cual significa que tendriamos una linea por cada pixel en la imagen. Por ejemplo, una imgen de 1920×1080 = 2073600 lineas con 8 bits de informacion cada linea.

Por que es importante destacar que esto sucede asi durante simulacion ? Pues porque algunas de estas palabras reservadas no son sintetizables dependiendo de la herramienta que utilizemos. Hoy en dia ya la mayoria de herramientas de sintesis tanto para FPGA como ASIC aceptan este tipo de inicializacion de memoria. Si nuestro sintetizador es lo suficientemente bueno, tomara estos archivos y los mapeará a una memoria ROM donde se almacenara la informacion de los bits de nuestra imagen.

Durante la simulacion esto solo es una variable que sera leida linea a linea y se le asignara a una señal que creemos por ejm RGB_in mientras que en Synthesis tenemos que realizar una interfaz que se conecte con la memoria, por ejemplo la mas simpel seria tomar dos señales donde una es memory_address que iria de entrada a la ROM y la salida de la rom estaria conectada a RGB_in.


EL filtro de sobel

El objetivo del post no es enseñar procesamiento de imagenes sino recalcar las diferencias y ventajas de una solucion en hardware en comparacion con su solucion en software. Sin embargo, es escencial conocer que el filtro de sobel corresponde a una multiplicacion de matrices escalar, a esta operacion se le suele llamar convolucion. La convolucion multiplica los valores de una matriz de entrada con un «Kernel» fijo y arroja un unico valor. El kernel en este caso es una matriz que realizará el filtro de la imagen. En este caso utilizaremos una matriz de 3×3. Un trozo de la imagen ira como entrada, se multiplicara con el kernel y arrojará una respuesta. El kernel en sobel es una matriz que tiene la siguiente forma:

Matrices del filtro de sobel. Imagen extraida de Wikipedia

La matriz Gx tiene esta forma para amplificar los valores cuando dos columnas difieren mucho en su valor cambian mucho y atenuar valores donde dos columnas extremas son casi del mismo valor.

La matriz Gy realiza lo mismo pero en las filas. De esta forma una de las matrices detecta los bordes horizontales y la otra los bordes verticales. Haciendo una media geometrica de ambos resultados de las matrices podremos obtener una imagen donde sean apreciables todos los bordes tanto verticales como horizontales.


FILTRO DE SOBEL EN PYTHON

Como indicamos el comienzo el filtro de sobel en python esta realizado con estructuras basicas en foor loops siendo esta la forma en la que se utilizaran instrucciones simples del CPU. Otro tipo de implementacion en software podria hacer uso de intrsucciones de CPU mas especificas, las cuales dependeran del CPU que tengas en tu PC.

Filtro de sobel implementado en Python

Se observa que para una imagen de 1920×1080 se tarda 9.37 segundos


FILTRO DE SOBEL: VERILOG

Como se indico anteriormente, no hemos realziado el hardware sino una simulacion del hardware en ModelSim Starter Edition. Del cual tenemos un tutorial de instalacion.

Simulacion del Hardware ejecutando el filtro de sobel usando Modelsim

Vemos que se tarda 9946120 ns lo que equivale a 10 ms

Comparativa de Python y Verilog [VIDEO]

No te olvides de darle un vistazo a nuestro video demostracion de este proyecto !

https://www.facebook.com/maelprosac/videos/303881448873356

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *