Logo Studenta

TFG-2877 MORENO FERNÃ_NDEZ, SAMUEL

¡Este material tiene más páginas!

Vista previa del material en texto

Equation Chapter 1 Section 1 
Trabajo Fin de Grado 
Grado en Ingeniería de las Tecnologías de 
Telecomunicación 
 
Herramienta de Reconocimiento de Imágenes en 
Python 
Autor: Samuel Moreno Fernández 
Tutor: Juan José Murillo Fuentes 
Dpto. Teoría de la Señal y Comunicaciones 
Escuela Técnica Superior de Ingeniería 
Universidad de Sevilla 
 Sevilla, 2020 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
iii 
 
Proyecto Fin de Carrera 
Ingeniería de Telecomunicación 
 
 
 
 
 
Herramienta de Reconocimiento de Imágenes en 
Python 
 
 
Autor: 
Samuel Moreno Fernández 
 
 
Tutor: 
Juan José Murillo Fuentes 
Catedrático de Universidad 
 
 
 
Dpto. de Teoría de la Señal y Comunicaciones 
Escuela Técnica Superior de Ingeniería 
Universidad de Sevilla 
Sevilla, 2020 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
v 
 
 
 
Trabajo Fin de Grado: Herramienta de Reconocimiento de Imágenes en Python 
 
 
 
 
Autor: Samuel Moreno Fernández 
Tutor: Juan José Murillo Fuentes 
 
 
El tribunal nombrado para juzgar el Proyecto arriba indicado, compuesto por los siguientes miembros: 
Presidente: 
 
 
 
Vocales: 
 
 
 
 
Secretario: 
 
 
 
 
Acuerdan otorgarle la calificación de: 
 Sevilla, 2020 
 
 
El Secretario del Tribunal 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vii 
 
A mi familia 
A mis amigos y compañeros 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ix 
 
Agradecimientos 
Quería agradecer a todas las personas que me han acompañado a lo largo de esta bonita etapa y me han 
ayudado a alcanzar la meta que me propuse hace tan solo cuatro años. 
A mis padres. Mi apoyo incondicional, mi fuente inspiración, quienes confían en mi cuando ni yo mismo soy 
capaz, desde el primer momento hasta el último de esta y de cualquier etapa de mi vida solo tuvieron la 
intención de ayudarme en no venirme abajo en ningún momento. Se los debo todo. Eternamente agradecido. 
A mi hermano, el pequeño de la casa, pero no por ello estoy continuamente aprendiendo de él. Una persona 
con un corazón tan grande, que en mis peores momentos incluso lo pasa peor que yo. Siempre estará a mi 
lado. 
A mis abuelos, se que los que no están aquí estarán profundamente orgullosos de mi desde el cielo, y que sin 
su esfuerzo no podría recoger los frutos que ahora estoy recogiendo. Mención especial a mis dos abuelas: una 
de ellas nos dejó durante mi etapa como estudiante universitario, y desde aquí le dedico este trabajo por su 
tremenda bondad y por ser una abuela ejemplar, Emilia, y a mi otra abuela quien reza cada vez que me 
examino para que apruebe, y que ha dado resultado, eres increíble Antonia. Mil gracias. 
A mis amigos, no fue fácil el momento en el que cada uno después de Bachillerato cogiera un camino distinto, 
pero hoy puedo decir orgulloso que son las personas con las que desconecto de todo, en quienes confio, me río 
con ellos y hacen que consiga ese pico de felicidad que hace tanta falta. 
A mis compañeros de piso, tantos lo que tuve el primer año como el resto de los años, compartiendo tantos 
buenos momentos y remando a contracorriente en las adversidades y épocas de exámenes. Grandes mis 
“Bros”. 
A mi tutor Juan José, por la atención recibida durante la pandemia vivida durante este curso. 
 
Samuel Moreno Fernández 
Sevilla, 2020 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
xi 
 
Resumen 
Este trabajo de fin de grado aporta al lector diferentes funciones para realizarle transformaciones a una imagen 
introducida por un usuario. A través de estas transformaciones, el usuario podrá encontrar diferentes objetivos 
que se encuentran en este trabajo: Transformada de Fourier, filtrado gaussiano, filtrado de mediana, su propia 
visualización 3D… El usuario tendrá una lista con todos los distintos tipos de tratamiento que se puede realizar 
sobre la imagen, y es el mismo usuario el que eligirá que transformación que realizará el programa. 
Una vez hecha una breve explicación sobre los objetivos, se tratará de explicar el lenguaje de programación en 
el que se implementa este trabajo, Python 3.8. Este lenguaje es el elegido para implementar el programa que 
llevará a cabo el tratamiento de las imágenes, y se utilizarán distintas librerías como NumPy y Matplotlib, para 
conseguir los resultados que queremos. 
Tras analizar Python y sus peculariedades, se explicarán las funciones definidas por el programador y todas las 
variables utilizadas a lo largo del programa, y el desarrollo de estas en el script GUI_img.py. 
Pero todas estas funciones creadas para transformar las imágenes tenemos que configurarlas de alguna manera 
para que interactúe con el usuario, y por ello se implementa una GUI (interfaz gráfica de usuario) usando la 
librería Tkinter en Python, siempre manteniendo cuidadosamente el tamaño de las imágenes, su relación de 
aspecto y sus propiedades para que se plasmen en la GUI sin ningún tipo de alteración. 
Finalmente, este programa se compilará para crear un archivo ejecutable .exe que funcione en Windows. Para 
ello se utilizará el compilador PyInstaller. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
xiii 
 
Abstract 
This final degree project provides the reader with different functions to perform transformations on an image 
entered by a user. Through these transformations, the user will be able to find different objectives found in this 
work: Fourier transform, Gaussian filtering, median filtering, their own 3D visualization… The user will have 
a list with all the different types of treatment that can be perform on the image, and it is the same user who will 
choose which transformation the program will perform. 
Once a brief explanation of the objectives has been made, the aim will be to explain the programming 
language in which this work is implemented, Python 3.8. This language is chosen to implement the program 
that will carry out the treatment of the images, and different libraries such as NumPy and Matplotlib will be 
used to achieve the results we want. 
After analyzing Python and its peculiarities, the functions defined by the programmer and all the variables 
used throughout the program will be explained, and the development of these in the GUI_img.py script. 
But all these functions created to transform the images we have to configure them in some way so that they 
interact with the user, and therefore a GUI (graphical user interface) is implemented using the Tkinter library 
in Python, always carefully maintaining the size of the images , its aspect ratio and its properties so that they 
are reflected in the GUI without any alteration. 
Finally, this program will be compiled to create an executable .exe file that works on Windows. For this, 
PyInstaller compiler will be used. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Índice 
Agradecimientos ix 
Resumen xi 
Abstract xiii 
Índice xiv 
Índice de Figuras xvii 
1 Introducción 1 
1.1 Objetivos 1 
1.2 Reconocimiento de imágenes 1 
1.2.1 Transformada de Fourier 2 
1.2.2 Filtrado de imágenes 2 
1.2.3 Visualización 3D y Contorno 2 
1.3 Estructura 3 
2 Software y diseño 5 
2.1 Software 5 
2.2 Python 5 
2.3 Entorno de Desarrollo Integrado(IDE) 6 
2.4 Herramientas de Python 7 
2.4.1 NumPy 7 
2.4.2 SciPy 8 
2.4.3 Os 8 
2.5 Herramientas de procesado de imagen 9 
2.5.1 OpenCV 9 
2.5.2 Matplotlib 9 
2.5.3 PIL 9 
2.5.4 Imutils 10 
2.6 Herramientas GUI 10 
2.6.1 Tkinter 10 
3 Herramienta y Desarrollo en Python 11 
3.1 Objetivo GUI 11 
3.2 Variables del programa 12 
3.2.1 Definición 12 
3.2.2 Variables en Python 12 
3.2.3 Variables globales 13 
3.2.4 Variables locales 13 
3.3 Funciones usadas de librerias 13 
3.3.1 Definición 13 
3.3.2 Implementación 14 
3.4 Diagrama de flujo 18 
4 Implementación en Python 19 
4.1 Fichero principal GUI_img.py 19 
4.2 Variables definidas por usuario 20 
xv 
 
4.2.1 Variables globales 20 
4.2.2 Variables locales 23 
4.3 Módulo principal 23 
4.4 Funciones definidas por usuario 26 
4.4.1 Get_mouse_posn(event) 26 
4.4.2 Update_sel_rect(event) 26 
4.4.3 Contour_y_3d() 27 
4.4.4 Histograma() 27 
4.4.5 NoRecorta() 29 
4.4.6 Recorta() 29 
4.4.7 Limpiar() 31 
4.4.8 ReconocimientoImagen() 31 
4.4.9 Choose() 36 
4.4.10 Save_file() 38 
4.4.11 Imprime_label(event) 40 
5 Compilación GUI 43 
5.1 Introducción 43 
5.2 PyInstaller 44 
5.2.1 Compilación programa 45 
6 Resultados de la GUI 47 
7 Conclusiones y Líneas futuras 63 
Referencias 66 
Glosario 69 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
xvii 
 
ÍNDICE DE FIGURAS 
 
Figura 1. Ejecución fichero.py desde Pycharm. 7 
Figura 2. Capas GUI. 12 
Figura 3. Definición de función en Python. 14 
Figura 4. Diagrama de flujos. 18 
Figura 5. Fases de la compilación. 43 
Figura 6. Análisis léxico. 43 
Figura 7. Análisis sintáctico. 44 
Figura 8. Instalación PyInstaller. 45 
Figura 9. Compilación programa en Python. 45 
Figura 10. Inicio de la GUI. 47 
Figura 11. Introducción de la imagen a tratar. 48 
Figura 12. Inicio con imagen introducida. 49 
Figura 13. Inicio con la selección del área recortada sobre la imagen. 50 
Figura 14. Inicio con recorte de la imagen. 51 
Figura 15. Tratamiento de la imagen, FFT. 52 
Figura 16. Tratamiento de la imagen, escala de grises. 53 
Figura 17. Tratamiento de la imagen, filtrado gaussiano. 54 
Figura 18. Tratamiento de la imagen, imagen ecualizada e histograma. 55 
Figura 19. Tratamiento de la imagen, filtrado de mediana. 56 
Figura 20. Tratamiento de la imagen, contornos. 57 
Figura 21. Guardar imagen tratada seleccionada. 58 
Figura 22. Contour y vista preliminar 3D de la FFT. 59 
Figura 23. Visualización 3D de la FFT. 60 
Figura 24. Inicio, limpieza de imagen. 61 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1 
 
1 INTRODUCCIÓN 
 
En nuestro día a día, tanto el ámbito laboral como en el cotidiano, estamos trabajando con imágenes, 
visualizando y analizándolas para intentar extraer información de ellas. Además, cualquier persona va 
recolectando a lo largo de la jornada imágenes con su cámara o su teléfono móvil, por ejemplo. También estas 
personas realizan de manera indirecta una serie de transformaciones a estas imágenes, como un simple cambio 
de escala, o un recorte sobre la imagen original. 
Los ingenieros de telecomunicaciones se encargan de que este tratamiento de las imágenes sea de la manera 
más sencilla posible para la persona que lo necesite. Así, a través de una interfaz gráfica se va a elaborar una 
herramienta en la que el cliente podrá realizar transformaciones indirectamente para extraer información de la 
imagen. Esta interfaz será sencilla para el público. 
Sobre ello trata la Herramienta de Reconocimiento de Imágenes, en la que se hacen una serie de 
transformaciones con la imagen que inserta el usuario para conseguir distintos objetivos: FFT, la imagen 
ecualizada, su visualización en 3D... 
 
1.1 Objetivos 
El objetivo principal del trabajo es implementar un software GUI que pueda ser fácilmente adaptado 
para crear un software de procesado de imagen y su posible distribución para uso de terceros. Para 
desarrollar esta GUI, utilizaremos la librería Tkinter, y utilizaremos otras librerías como NumPy y 
Matplotlib para realizar todas las transformaciones necesarias. 
 
Las transformaciones realizadas han sido estudiadas en el grado, como la Transformada de Fourier, y 
plasmaremos los resultados en distintas pestañas de la interfaz gráfica. 
 
Otro de los objetivos será que el usuario pueda interactuar sin ningún tipo de problema con la interfaz, y 
que pueda hacerlo entendiendo todo lo que esta manejando sobre el software. Para que esto sea así, el 
diseño de la GUI debe estar muy cuidada y ordenada respecto a los widgets (elementos) que la 
conforman. 
 
La idea sobre un futuro uso o una posible mejora de la interfaz es aumentar el número operaciones 
sobre el procesamiento de imagen (nuevos filtrados, aumento de brillo…) , y que estas imágenes 
transformadas imprimirlas o bien en la misma pestaña o tab o crear una nueva pestaña, siempre que 
dentro de esta pestaña haya una relación estrecha en el tratamiento de la imagen. De esta manera el 
ingeniero que quiera adaptar este software tendrá varias posibilidades de hacerlo. 
 
 
1.2 Reconocimiento de imágenes 
 
Una vez el usuario introduce la imagen elegida para el tratamiento, la herramienta realiza una serie de 
transformaciones a esta imagen, y se obtiene como resultado [10]: 
 
• Escala de grises. Es la misma imagen introducida, pero la gama de colores se reduce a una 
escala de grises. 
 
 
 Introducción 
 
 
2 
• FFT. Transformada rápida de Fourier de la imagen que se describe a continuación. 
 
• Filtrado de Mediana. Suaviza la imagen, reduce la cantidad de variaciones de intensidad entre 
píxeles vecinos. Consigue que las intensidades de los objetos pequeños se mezclen con el 
fondo con el fin de detectar los objetos de mayor tamaño. Elimina ruido. 
 
• Filtrado gausiano. Similar al Filtrado de Mediana, aunque produce un suavizado más uniforme. 
 
• Imagen ecualizada. Eliminación total del ruido. 
 
 
• Contorno imagen. Líneas que permiten trazar los límites de la imagen. 
 
 
• Visualización 3D. Representación tridimensional de la figura correspondiente. En este caso, se 
realiza una visualización 3D de la FFT de la imagen. 
 
 
1.2.1 Transformada de Fourier 
Es una transformación matemática que transforma señales entre los dominios del tiempo y de la 
frecuencia. Hace corresponder a una función f(t) con otra función F(w). 
 
F(w) = ∫ 𝑓(𝑡)𝑒−𝑖𝑤𝑡
+∞
−∞
𝑑𝑡 , y su transformada inversa 
 
f(t) = 
1
2𝜋
∫ 𝐹(𝑤)𝑒−𝑖𝑤𝑡
+∞
−∞
𝑑𝑤, 
 
Las imágenes que conocemos, suelen estar en el dominio del tiempo, y estas la transformaremos para 
obtener su resultado en el dominio de la frecuencia a través del uso de distintas librerías. 
 
1.2.2 Filtrado de imágenes 
El resultado de cada pixel se obtiene como combinación lineal de sus vecinos. Multiplicamos el entorno 
de cada pixel por una mascara, la media ponderada será el nuevo valor del pixel. 
Estos filtros operan en el dominio del tiempo. 
Dependiendo del tipo de filtrado (mencionados en 1.2), se usarán unas funciones u otras para encontrar 
el objetivo. 
 
1.2.3 Visualización 3D y Contorno 
Respecto al contorno, consiste en encontrar la silueta o siluetas de todas las figuras distintivas que haya 
o se aprecien dentro de la imagen insertada. Estas formas, estarán reproducidas con unas líneas de color 
fluorescente. 
A través de la visualización 3D, se simula una imagen de dos dimensiones en tres dimensiones. Así, 
visualizamos la imagen, que en nuestro caso será la FFT de la imagen insertada por el usuario, desde 
 
3 
 
3 Herramienta de Reconocimiento de Imágenes en Python 
 
diferentes perspectivas. 
1.3 Estructura 
El resto del presente documento está dividido en 5 capítulos: 
 
 
• Segundo capítulo: se explicará el lenguaje y la IDE escogida,y todas las librerías usadas para 
implementar esta herramienta. Este capítulo tiene una gran importancia para entender la 
implementación del programa. 
 
• Tercer capítulo: se hace una introducción general a Python como toma de contacto con el 
lenguaje. Este capítulo incluye la explicación del significado de conceptos básicos, tipos de 
datos, funciones usadas ya implementadas en las librerías… 
 
• Cuarto capítulo: se combinarán diseño e implementación del funcionamiento del programa. Se 
tendrá en cuenta el aspecto de la GUI. 
 
• Quinto capítulo: Compilación en PyInstaller del programa implementado en Python 3.8. 
 
 
• Líneas futuras y Conclusiones: centradas sobre todo en implementaciones y mejoras que se 
pueden realizar a partir de la realización del trabajo. También recapitulará todas las 
conclusiones que se hayan podido extraer a lo largo del trabajo y en la implementación del 
sistema. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Introducción 
 
 
4 
 
 
5 
 
 
2 SOFTWARE Y DISEÑO 
 
 
 
 
 
 
2.1 Software 
En la actualidad existen multitud de lenguajes de programación y entornos para desarrollar distintas 
aplicaciones y herramientas. Para esta herramienta, vamos a implementar una GUI y hay multiples 
lenguajes que nos permiten desarrollar una interfaz gráfica. Entre ellos están Matlab, Java, JavaScript, 
C, C++ … y Python. Este ultimo es el elegido para crear nuestra interfaz. 
El motivo principal sobre la elección de hacer el problema en Python es porque es un requisito de 
partida. Además, es un lenguaje que se focaliza en conseguir una sintaxis fácil de leer, y eso ayudará a 
la comprensión total del Código [1]. 
 
2.2 Python 
Este lenguaje de programación está presente en muchas aplicaciones y sistemas operativos, como iOS, 
Windows, Linux, Mac o Android, debido a que tiene una curva de aprendizaje moderada, con un 
Código legible. 
Es un Código versátil multiplataforma que se destaca por su Código limpio. Su éxito principalmente se 
debe a que es un Código abierto, que permite su uso desde cualquier rincón del mundo. 
Es importante destacar que en este software se trata con la version Python 3.8 (32 bits), actualmente la 
más reciente. 
Tiene como características [2]: 
 
• Lenguaje multiplataforma. Se puede usar en distintos sistemas operativos 
• Ideal para trabajar con volúmenes de datos muy grandes, favorece el procesamiento, siendo 
también el lenguaje utilizado por las empresas de Big Data. Algunas de sus ventajas son: 
Sencillez y presteza, selecto, legible, fácil de aprender, organizado, portable y con un gran 
número de usuarios que participant activamente en su Desarrollo. 
 
Creo que este es el mejor consejo: piensa 
constantemente cómo podrías hacer mejor las cosas. 
 
 -Elon Musk- 
 
 
Software y diseño 
 
 
6 
• Imperativo. Describen el estado del programa y permiten la modificación mediante 
instrucciones de Código. Se describe paso a paso un conjunto de instrucciones. 
• Funcional. Variación del programa mediante la mutación y el cambio de variables. Así, se 
opera con datos de entrada y salida. 
• Orientado a Objetos. Los objetos manipulan a otros, para ofrecer una salida específica. 
También permite juntar librerías. 
• Dinámico. Una variable puede tomar distintos valores de diferentes tipos en distintos 
momentos. 
Es este el Código que utilizaremos para desarrollar la Herramienta de Reconocimiento de Imágenes, 
para poder trabajar con mayor facilidad todos los datos que componen una imagen. 
 
En Python, a los archivos se le coloca la extension .py de forma que se pueden incorporar paquetes. 
Esta incorporación de paquetes y librerías se realiza de distintas maneras: 
• Mediante el comando import paquete. 
• Mediante el comando import paquete.elemento. 
• Mediente from paquete import elemento. 
• Mediante import elemento as name_elemento, acortando el namespace del element. 
2.3 Entorno de Desarrollo Integrado (IDE) 
Para que el lenguaje tenga una finalidad final, debemos desarrollarlo en un entorno de Desarrollo 
interactivo, que es una aplicación que nos proporciona servicios para facilitar al programador el 
Desarrollo software [3]. 
En este caso, como se ha desarrollado la GUI en Python, se ha escogido el entorno PyCharm. PyCharm 
es uno de los entornos de Desarrollo más completos. Cuenta con entornos para construir Código en 
distintos lenguajes como PHP o Ruby. Usaremos la versión “Community” que es gratuita. También 
para posibles usos futuros, existe el modelo “Professional” de pago, ideal para el Desarrollo web. 
El objetivo principal de este IDE es proveer un entorno de programación en Python que se ejecuta de 
forma concurrente. 
La version utilizada de Pycharm es Pycharm 2019.3.3 (Community Edition). 
Pycharm ofrece distintos servicios [3]: 
 
• Asistencia inteligente a Python. Pycharm proporciona una finalización del Código inteligente, 
inspecciones del Código, indicación de errores sobre la marcha y arreglos rápidos, así como 
refactorización de Código automática y completes funcionalidades de navegación. 
• Marcos de trabajo de Desarrollo web. Pycharm ofrece una gran compatibilidad con marcos de 
trabajo de Desarrollo web modern como Django, Flask, Google App Engine… 
• Herramientas científicas. Cuenta con una consola de Python interactive y es compatible con 
Anacando y varios paquetes científicos como matplotlib y NumPy. 
• Desarrollo multitecnología. Además de Python, PyCharm es compatible con JavaScript, 
HTML/CSS… 
• Capacidades para Desarrollo remote. Ejecuta, depura, prueba y desarrolla aplicaciones en 
máquinas virtuales 
 
7 
 
7 Herramienta de Reconocimiento de Imágenes en Python 
 
• Herramientas de Desarrollo. Una gran colección de herramientas listas para usar, como un 
depurador integrado y ejecutor de pruebas. 
• IDE multiplataforma. PyCharm funciona en Windows, Mac OS o Linux. Es posible instalar y 
ejecutar PyCharm en tantas máquinas como se tenga, y usar el mismo entorno y la misma 
funcionalidad. 
• Cabe destacar que PyCharm está diseñado por programadores y para programadores, con el fin 
de proporcionarles herramientas que son necesarias para un desarrollo productivo de Python. 
 
En la siguiente figura, hay un ejemplo del aspecto de la IDE que vamos a usar para desarrollar la 
aplicación, Pycharm. También la ejecución desde Pycharm de un fichero como ejemplo de 
funcionamiento, y las distitas pestañas y opciones que se abren en la IDE para tener una vision global 
de la configuración del fichero, que librerías usa, plot, distintas excepciones lanzadas si procede… [17] 
 
 
2.4 Herramientas de Python 
2.4.1 NumPy 
Biblioteca de funciones matemáticas que opera con matrices. 
Numpy, que significa “Numerical Python”, es la librería principal para la informática científica, que 
proporciona grandes estructuras de datos [5]. 
La versión utilizada de NumPy es NumPy v1.18.0. 
Tiene como características [5]: 
 
Figura 1. Ejecución fichero .py desde Pycharm. 
 
Software y diseño 
 
 
8 
• Implementación de matrices N-dimensionales 
• Contiene: integrales, generadores de números totalmente aleatorios, transformadas de Fourier… 
• Interoperabilidad. Permite plataformas de hardware. 
• Fácil de usar. Alto nivel de sintaxis que facilita la accesibilidad a cualquier programador. 
• Código abierto. Mantenido por la comunidad diversa GitHub. 
• Muy utilizado en el desarrollo de algoritmos de Machine Learning 
 
Esta librería ha tenido gran éxito en el estudio de ciertos casos: gracias a NumPy, junto con el uso de 
otras librerías como SciPy y Matplotlib, permitió al Event Horizon Telescope producir la primera 
imagen de un agujero negro, también científicos confirmaron la existencia de ondas gravitacionales 
que predijo Albert Einstein en 1916 [5]. 
 
2.4.2 SciPy 
Paquete científico científico. Incluye librerías científicas, basadas para matemáticas, ciencias e 
ingeniería.Es una colección con algoritmos numéricos y cajas de herramientas específicas de dominio, 
que incluye procesamiento de señales, optimización, estadísticas y mucho más [6]. 
Se basa en NumPy, y es parte del conjunto NumPy, con herramientas como SymPy o Pandas. 
Algunas características son [11]: 
 
• Está programado en Python, C, Fortran, C++, Cython. 
• La comunidad de personas pertenecientes a SciPy, son las mismas que desarrollan esta pila. 
• Contiene módulos para optimización, álgebra, integración, FFT, procesamiento de imágenes… 
• Multiplataforma. 
• Software abierto para computación científica. 
• Proporciona rutas numéricas. 
• Cómputo de datos y experimentación científica e informática. 
 
2.4.3 Os 
Este módulo viene incorporado en el sistema Python, y nos permite acceder a funcionalidades 
dependientes del sistema operativo. Permite acciones como crear una carpeta, listar contenidos de una 
carpeta, conocer acerca de un proceso, finalizar un proceso, etc. 
Facilita métodos para conocer el directorio en el que nos encontramos, crear un directorio distinto o 
eliminar archivos [9]. 
Notas sobre la disponibilidad de estas funciones [23]: 
 
• El diseño de los módulos de Python dependientes del sistema operativo incorporado es tal que, 
siempre que esté disponible la funcionalidad, utilizará la misma interfaz. 
• Las extensiones propias de un sistema operativo en particular también están disponibles en el 
módulo Os. 
 
9 
 
9 Herramienta de Reconocimiento de Imágenes en Python 
 
• Todas las funciones que afirman “Disponibilidad: Unix” son también compatibles con Mac OS 
X, que se basa en un núcleo de Unix. 
 
 
2.5 Herramientas de procesado de imagen 
 
2.5.1 OpenCV 
Biblioteca de software de código abierto. Proporciona una infraestructura común para aplicaciones de 
visión por computadora [4]. 
La librería OpenCV tiene más de 2500 algoritmos optimizados, que incluyen aprendizaje automático. 
Estos algoritmos se suelen utilizar para reconocer caras, identificar objetos, estraer modelos 3D, nubes 
de puntos, unir imágenes, recortes con alta resolución, buscador de imágenes parecidas en bases de 
datos, eliminación de ojos rojos en fotografías o imágenes con flash, reconocimiento de paisajes, 
realidad aumentada…[4] 
Tiene interfaces C++, Python, Java y MATLAB y es compatible con Windows, Linux, Android y Mac 
OS [4]. 
Está escrita en C++ y tiene una interfaz con plantilla que funciona a la perfección con contenedores 
STL [4]. 
En este software, se usa la versión 4.2.0 de OpenCV. 
 
2.5.2 Matplotlib 
Biblioteca completa para crear visualizaciones estáticas e interactivas en Python. Permite desarrollar 
gráficos de calidad de publicación con solo unas pocas líneas de código. Toma el control total de estilos 
de línea, propiedades de los ejes [8]… 
En este software, se usa la versión 3.2.0 de Matplotlib. 
Algunas de sus características son [8]: 
 
• Como función principal genera gráficos a partir de datos en listas. 
• Proporciona una pylab, una API implementada para parecerse a MATLAB. 
• Amplio juego de herramientas. Incluyen trazado 3d en el kit de herramientas mplot3d. 
• Paquetes de terceros. Proyecciones y mapeos de imágenes. 
• Código abierto. Mantenido por la comunidad diversa GitHub. 
 
2.5.3 PIL 
“Python Imagin Library”, es una biblioteca de imágenes de Python que agrega capacidades de 
procesamiento de imágenes. Soporta una variedad de formatos, incluidos GIF, JPEG y PNG. Maneja 
imágenes como rectángulos de datos de píxeles [21]. 
Admite diversos y múltiples formatos y proporciona potentes habilidades de procesamiento de 
imágenes y gráficos. 
 
Software y diseño 
 
 
10 
Gracias a PIL, creamos imágenes, las manipulamos, creamos e insertamos textos en ellas, y esto 
lanzando un script [21]. 
En este software se usa la versión 7.0.0 PIL. 
Código fuente abierto y mantenido por la comunidad GitHub. 
 
2.5.4 Imutils 
Serie de funciones que facilitan algoritmos y funciones de procesamiento de imágenes, como la 
traducción, rotación, recortes, ampliaciones de tamaños y visualización de imágenes Matplotlib con 
OpenCV. 
En este software se usa la versión 0.5.3 Imutils. 
2.6 Herramientas GUI 
2.6.1 Tkinter 
Python tiene multitud de marcos para elaborar una GUI, pero Tkinter es el único marco integrado en la 
biblioteca estándar de Python. 
Permite crear, colocar y mover una variedad de elementos gráficos para control, información de entrada 
y salida (widgets) [7]. 
En este software se usa la versión 8.6 de Tkinter. 
Algunas de sus características son [12]: 
 
• Multiplataforma. El mismo código funciona en Windows, macOS y Linux. Los elementos 
visuales pertenecen a la plataforma donde se ejecutan. 
• Instalada por defecto en una instalación Microsoft Windows. 
• Algunas de sus funciones son: posiciona texto/imagen en cualquier lugar de un widget, indica 
colores de fondo de widget, posibilidad de especificar el ancho del borde de un elemento, nos 
permite crear un botón y nos asocia un método o función para cuando se pulse ese botón… 
• Ideal cuando el principal objetivo es construir algo funcional y multiplataforma. 
 
 
 
 
 
 
 
 
 
 
 
 
 
11 
 
3 HERRAMIENTA Y DESARROLLO EN PYTHON 
 
 
 
3.1 Objetivo GUI 
La interfaz gráfica de usuario (GUI), es un sistema informático que interviene como interfaz, usando un 
conjunto de objetos gráficos para representar información y permitir al usuario realizar una serie de 
acciones. Su principal uso consiste en ofrecer al usuario un entorno visual sencillo que permite la 
comunicación con el sistema operativo del ordenador [13]. 
Por citar ejemplos, algunos son [13]: 
• Windows 
• X-Windows de Linux 
• Aqua de Mac OS X 
En relación con la interacción con el usuario, es un artefacto tecnológico que posibilita una interacción 
con un sistema informático. 
En este caso, el sistema informático es la Herramienta que hemos creado para trabajar con imágenes 
que el usuario decide introducir en el sistema. A través de esta GUI, programada en Python y basada en 
la librería Tkinter, el usuario podrá realizar una serie de operaciones a la imagen, simplemente 
clickando un botón. De esta manera tan sencilla, el usuario podrá percibir visualmente los cambios 
generados en la imagen (Imagen original en escala de grises, FFT de la imagen…) [13]. 
Todo este procesado de imagen se comentará con detalles en los capítulos posteriores. 
Como se observa en la Figura 2, a través de la manipulación directa del usuario se interactúa con la 
interfaz gráfica de usuario. Este artefacto tecnológico posibilita a través de la representación del 
lenguaje visual, una interacción interesante con un sistema informático. Algunos ejemplos de interfaz 
gráfica son KDE Plasma, los entornos de escritorios de Windows… Esta interfaz gráfica está 
directamente relacionada con el servidor de pantalla, programa que coordina y gestiona las entradas y 
salidas de sus clientes (X.org, muy conocido en el mundo de Linux). Estos servidores de pantalla están 
directamente relacionados con los gestores de ventanas que crean los efectos gráficos y hacen que se 
muestren en las ventanas. Otra parte importante a la hora de crear una GUI es tener en cuenta el núcleo, 
que es la parte fundamental del sistema operativo, y es el responsable de facilitar a los distintos 
programas o interfaces de gestionar un acceso seguro al hardware de la computadora [24]. 
 
 
 
 
 
Sé que parece que el mundo se está desmonorando, 
pero en realidad es una gran época para volvernos 
locos, seguir nuestra curiosidad y ser ambiciosos. No 
abandonéis vuestros sueños. ¡El mundo os necesita! 
- Larry Page - 
 
 
Herramienta y Desarrollo en Python 
 
 
 
12 
 
 
Figura 2. Capas GUI. 
 
3.2 Variables del programa 
3.2.1 Definición 
En programación está la definición de “variable”, que es similar pero no idéntico al concepto de 
variable en lasmatemáticas. 
Las variables están asociadas a “algo” en concreto. Además, cada lenguaje tiene una manera distinta de 
implementar tal concepto, por lo que las definiciones siguientes [14]: 
• En algunos lenguajes, una variable se puede entender como una caja en la que se guarda un 
valor. Esta variable o caja, corresponde a un lugar en la memoria del ordenador. 
• Se pueden representar con letras o palabras: x, a, c, variable, edad, ciudad… 
• Para asignar un valor a estas variables, se suele hacer con el símbolo de igualdad (=), 
entendiéndose como una asignación. Cuando se realizar esta asignación, le pedimos al 
programa que calcule lo que existe a la derecha de esta igualdad, y que lo guarde en la variable 
lo que haya calculado previamente. 
La información que se guarda en estas variables puede ser de varios tipos como, por ejemplo [14]: 
• Números, que estos a su vez pueden ser enteros, decimales, imaginarios… 
• Cadenas de texto, como una sola letra o un conjunto de juego de caracteres ASCII. 
• Conjuntos de números o texto, como matrices. 
• Estructuras, como punteros. 
3.2.2 Variables en Python 
En Python, el concepto de variable cambia. Estas variables, entendidas anteriormente como “cajas” de 
 
13 
 
13 Herramienta de Reconocimiento de Imágenes en Python 
 
información para otros lenguajes de programación, se convierten en “etiquetas” que hacen referencia a 
los datos en Python. 
Python es un lenguaje de programación orientado a objetos, y su modelo también lo es. Para cada dato 
de un programa, Python crea un objeto. Cada objeto tiene [14]: 
• Identificador único. Número entero distinto para cada objeto. 
• Tipo de datos. Entero, decimal, cadena de caracteres… 
• Un valor. Propio del dato. 
 
Volviendo un poco a las variables que existen en Python, distinguimos tres tipos [14]: 
• Variables locales. Las variables locales son las que pertenecen al ámbito de la subrutina. 
También son accesibles a niveles inferiores. No necesitan identificación. 
• Variables globales. Pertenecen al ámbito del programa principal. Necesitan la identificación 
global. 
• Variables no locales. Pertenecen a un ámbito superior a las locales, pero no son globales. 
Necesitan la identificación nonlocal. 
 
En la GUI desarrollada en la Herramienta de reconocimiento de imágenes, distinguiremos 
principalmente entre dos tipos de variables: las variables globales y las variables locales. 
3.2.3 Variables globales 
Si a una variable no se le asigna valor, Python la considerará libre, y busca su valor en niveles por 
encima a esa función. Si a la variable se le asigna un valor en el programa principal, se le considerará 
global. 
Si queremos cambiar el valor de estas variables globales en alguna función o subrutina, debemos 
declararla dentro de la función o subrutina como global nombre_variable. Así, en la subrutina se 
utilizará la variable con el valor del programa principal, o igualmente se podrá modificar el valor de esta 
variable para utilizarla posteriormente en el programa principal [14]. 
3.2.4 Variables locales 
Son las variables a las que se le asigna un valor dentro de una función, y solo existen en la propia 
función, incluso cuando en el programa exista otra variable con el mismo nombre. 
No son accesibles desde otros niveles superiores. 
3.3 Funciones usadas de librerias 
3.3.1 Definición 
 Una función o subrutina es un bloque de código con un nombre, que recibe cero o X argumentos como 
entrada, sigue una secuencia de sentencias que tienen alguna finalidad y operación deseada, y 
devuelven y/o realizan una tarea en el programa en el que se encuentran [22]. 
Las funciones son llamadas siempre que se necesiten en el programa principal. 
Son esenciales para la programación estructurada, característica de Python. Algunas de las ventajas de 
las funciones son [22]: 
 
Herramienta y Desarrollo en Python 
 
 
 
14 
• Modularización. Segmenta un programa amplio y completo en distintos módulos más simples, 
facilitando la programación y el depurado. 
• Reutilización. Estos subbloques permiten realizar una función en distintos programas. 
 
Las funciones definidas por usuario son usadas habitualmente. Es una sentencia ejecutable, que 
enlaza el nombre de la función a un objeto función. 
Estas funciones se definen con la sentencia def, de la siguiente forma que se explica en la figura: 
 
 
La definición de una función no ejecuta el cuerpo de la función, lo que sucedería solamente con la 
llamada de la función en alguna parte del programa principal. 
3.3.2 Implementación 
La implementación de las funciones definidas por el usuario, necesitan de funciones ya implementadas 
en librerías importadas en el programa. 
Estas funciones necesitan uno, ninguno o varios argumentos de entrada, para proporcionar una, ninguna 
o varias salidas. 
Estas funciones pertenecen a librerías, e iremos explicando cada una de las funciones utilizadas según la 
librería en la que se describan. 
A continuación, están todas las funciones integradas que utilizaremos en la realización de la 
Herramienta en Python. 
• Librería NumPy. Nos agrega funciones de apoyo para el cálculo de vectores y matrices de alto 
nivel. 
o Numpy.arange(0, A). Devuelve valores espaciados uniformemente dentro de un 
intervalo dado, en este caso de 0 a un número desconocido A. 
 
o Numpy.meshgrid(Y, X). Devuelve dos matrices de coordenadas de vectores de 
coordenadas X e Y. 
 
o Numpy.array([A, A, A]). Devuelve una matriz de valor A en cada posición. Si en vez 
de introducir como argumento un vector, introducimos una imagen, esta se recoge 
como un array y devuelve una matriz. 
 
o Numpy.fft.fft2(image, [256,256]). Calcula la FFT bidimensional. La matriz de entrada 
(image) puede ser compleja. Nos devuelve un ndarray. 
 
Figura 3. Definición de función en Python. 
 
15 
 
15 Herramienta de Reconocimiento de Imágenes en Python 
 
o Numpy.fft.fftshift(f). Siendo f la FFT de la anterior sentencia, esta función cambia el 
componente de frecuencia cero al centro del espectro. 
 
o Numpy.abs(fshift). Calculamos la amplitud del espectro fshift. 
 
o Numpy.log(k). Realiza el logaritmo a un conjunto de número o número introducido K. 
 
• Librería OpenCV 
o Array.shape. Devuelve el tamaño de la cadena de caractéres Array. 
 
o Cv2.imread(ruta,bandera). El método carga una imagen del archivo especificado en la 
ruta para llegar hacia él. Con las banderas especificadas, podemos cambiar la forma de 
leer la imagen. 
 
o Cv2.calcHist(imagen, rangos). Cálculo de histograma de la imagen insertada. Hay 
diferentes opciones a insertar, pero la más importante es el rango en el que se va a 
mover el histograma. 
 
o Cv2.cvtColor(). Convierte una imagen de un espacio de color a otro. Hay más de 100 
métodos de conversión disponibles en OpenCV. Por ejemplo, están 
Cv2.COLOR_BGR2RGB y Cv2.COLOR_BGR2HSV [15]. 
 
o Cv2.inRange(imagen, lowB, upB). Donde se introduce una imagen, y nos 
encontramos con un umbral donde asignamos un valor particular a la región que se 
encuentre entre los dos umbrales “lowB” y “upB”. Al resto de la región se le asigna un 
valor distinto. 
 
o Cv2.GaussianBlur(Imagen). Se aplica un suavizado gaussiano en la imagen de origen 
de entrada. 
 
o Cv2.medianBlur(Imagen). El elemento central de la imagen se reemplaza por la 
mediana de todos los píxeles en el área del núcleo. 
 
o Cv2.findContours(). Ayuda a extraer los contornos de la imagen. 
 
• Librería Matplotlib 
o Plt.figure(). Clase personaliza en la interfaz de pyplot. Relacionada con la 
visualización de figuras. Devuelve “Fig”. 
 
o Fig.gca(projection=’3d’). La figura “Fig” pasa a representarse en 3 dimensiones. El 
resultado lo llamaremos “Ax”. 
 
o Ax.contourf(XX, YY, imagen_array). Dibuja líneas de contorno y rellenos. XX e YY 
 
Herramienta y Desarrollo en Python 
 
 
 
16 
son matrices que conforman el dimensionamiento de la matriz que compone laimagen. 
 
o Plt.close(). Cierra una ventana de figura. 
 
o Matplotlib.pyplot.imsave(ruta, matriz). Guarda una matriz como un archivo de 
imagen, en una ruta seleccionada previamente. 
 
• Librería PIL 
o Imagen.crop(). Metodo usado para recortar una porción rectangular de cualquier 
imagen. 
 
o Imagen.resize(A,B). Devuelve una imagen con cuyo alto y ancho se ha pasado como 
parámetros A y B. 
 
o Image.fromarray(matriz). Crea una memoria de imagen a partir de un objeto que 
exporta la interfaz de matriz. 
 
• Librería Tkinter. Trataremos elementos Canvas, que proporciona funciones de gráficos 
estructurados que se puede utilizar para dibujar diagramas. 
o Tkinter.Tk(). Instancia de la clase Tk, de Tkinter. Es el administrador de ventanas con 
botones de cerrar, maximizar y minimizar en la parte superior como una GUI habitual. 
A esta instancia la llamaremos “raíz” para entender las siguientes funciones. 
 
o Raíz.geometry(“AxB”). Establece unas dimensiones AxB a la ventana raíz. 
 
o Raíz.title(“Titulo de la Herramienta”). Titulo del administrador de ventanas. 
 
o Raíz.config(). Aquí se pueden configurar distintos parámetros relacionados con el 
administrador de ventanas. Por ejemplo, modificar los bordes, el tipo de cursor, el 
color de fondo… 
 
o Raiz.mainloop(). Se ejecuta cuando la aplicación esta lista para realizarse. Bucle 
infinito. 
 
o Tkinter.Label(Raíz, text=’ ‘). Etiqueta de texto, que suele ser estático. También puede 
ser una etiqueta de imagen. Al resultado devuelto por esta función lo llamaremos 
Label. 
 
o Label.place(x=”A”, y=”B”). Posición del label dentro de la ventana en la que está 
incluida. 
 
 
17 
 
17 Herramienta de Reconocimiento de Imágenes en Python 
 
o Tkinter.Frame(Raíz). Funciona como un contenedor, que se encargar de organizar la 
posición de los widgets. 
 
o Tkinter.Canvas(Raíz). Crea un widget de propósito general para mostrar gráficos en 
raíz. Al resultado de este widget lo llamaremos “Canvas”. 
 
o Canvas.create_rectangle(topx, topy, topx, topy, dash=(2,2), fill=’’, outline=’white’). 
Dibuja un rectángulo discontinuo de color blanco en el área seleccionada en este 
widget con el ratón. El rectángulo creado lo llamaremos “Rectángulo”. 
 
o Canvas.create_image(0,0,image=Imagen). En este widget se incluye la imagen que se 
quiere introducir. 
 
o Canvas.coords(Rectángulo, topx, topy, botx, boty). Si se dan las coordenadas, como en 
este caso, estas se reemplazarán por las coordenadas actuales del ítem seleccionado. 
 
o Canvas.bind(‘<Button-1>’, función). Esta función se ejecuta cada vez que se clickea el 
botón derecho del ratón. “Función” es a la subrutina que se llama cuando esto pasa. 
 
o Tkinter.Button(Raíz). Crea un Botón en el administrador de ventanas Raiz. 
 
o ImageTk.PhotoImage(Imagen). Produce una imagen compatible con Tkinter. Esto se 
puede usar en todas partes donde Tkinter espera un objeto imagen. 
 
o Widget.Destroy() . Destruye el widget selecionado. 
 
o Filedialog.askopenfilename(). Función para crear un objeto de diálogo de archivo. 
Puede ser bien para abrir el archivo, para guardar el archivo, o para abrir el directorio. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Herramienta y Desarrollo en Python 
 
 
 
18 
 
 
3.4 Diagrama de flujo 
Este diagrama representa el funcionamiento de la interfaz gráfica de usuario. 
 
Figura 4. Diagrama de Flujos. 
 
 
 
 
19 
 
4 IMPLEMENTACIÓN EN PYTHON 
 
El software es como la entropía: dificil de atrapar, no pesa, y cumple la 
Segunda Ley de la Termodinámica, es decir, tiende a incrementarse. 
 
-Norman Augustine- 
Python es un lenguaje de programación diferencial, y por ello se escoge este lenguaje por delante de otros 
también muy usados como Java o Node.js [16]. 
Muchísimas ventajas mencionadas anteriormente como ser un lenguaje multiparadigma, orientado objetos e 
interpretado… hacen a Python ser el segundo lenguaje con mayor crecimiento en los últimos años, y ser el 
elegido por la mayoría de los ingenieros, desarrolladores y científicos a la hora de crear o desarrollar una 
Herramienta software [16]. 
A continuación, se explica el desarrollo del programa, sus partes, las variables utilizadas, tanto globales como 
locales, el módulo principal y las funciones creadas por el desarrollador para implementar la herramienta. 
Antes de comenzar, sería útil definir el concepto de widget, sencillo pero que vamos a nombrar a lo largo de 
este capítulo. Un widget es un componente que aparece dentro de nuestra ventana raíz. Se distinguen 21 tipos 
de widgets distintos: Canvas widget, Lavel widget, Button widget… con diferentes utilidades. 
4.1 Fichero principal GUI_img.py 
El programa está compuesto exclusivamente por este fichero donde se encuentran todas las variables, 
tanto locales como globales, declaradas. De esta manera, también están las funciones definidas por el 
desarrollador, que explicaremos más adelante. 
Este fichero corresponde a un archivo de script de Python. Para crearlo, primeramente, se tiene que 
recurrir a la IDE elegida que en este caso es PyCharm. 
Se importan todas las librerías mencionadas en el capítulo anterior. 
Código: 
 
from tkinter import * 
from tkinter import filedialog 
from tkinter import ttk 
import tkinter as tk 
import cv2 
from numpy import * 
import numpy as np 
import matplotlib as matplotlib 
from matplotlib import pyplot as plt 
from PIL import Image, ImageTk 
 
Implementación en Python 
 
 
 
20 
import scipy.misc as scimis 
import imutils 
from mpl_toolkits.mplot3d import axes3d 
from os import remove 
4.2 Variables definidas por usuario 
Estas etiquetas son las utilizadas por el desarrollador para hacer referencia en el programa a diferentes 
valores o datos. 
Distinguimos entre las variables globales y locales, cuyas diferencias están explicadas anteriormente. 
4.2.1 Variables globales 
Estas variables son usadas en todo el programa. Para la “Herramienta de reconocimiento de imágenes 
en Python”, vamos a usar las siguientes, con sus distintas funcionalidades que se describen a 
continuación: 
 
• Path_global: Contiene la ruta a la imagen original introducida por el usuario. A través de 
ella, se puede leer la imagen de la manera que mejor convenga. 
 
• Image_1_global: Contiene la imagen en forma de array introducida por el usuario. Si la 
imagen no ha conseguido leer sería una matriz vacía. Carga la imagen a color. 
 
• Hsv_global: Cambio de espacio de color de Image_1_global para representar mejor los 
colores. 
 
• Mask_global: Detecta los colores de Image_1_global en un rango definido [0,255]. 
 
• B_global: Etiqueta del botón que llama a la función correspondiente a recortar la imagen 
original, y hacer que sea la imagen activa para trabajar en la GUI. 
 
• B1_global: Etiqueta del botón que llama a la función correspondiente a devolver a la 
imagen original a la imagen activa para trabajar en la GUI. 
 
• B2_global: Etiqueta del botón que hace que el programa comience a realizar una serie de 
transformaciones sobre la imagen activa en la GUI. 
 
• MagnitudFFT_global: Representa a la FFT de la imagen activa en la GUI, es decir, la 
imagen original o una imagen recortada sobre la original. 
 
• MagnitudFFT2_global: Representa a un objeto ImageTk, que es una imagen adaptada a 
Tkinter. Esta imagen es la FFT de la imagen activa en la GUI. 
 
21 
 
21 Herramienta de Reconocimiento de Imágenes en Python 
 
 
• Imagen_ecualizada_global: Representa a un objeto ImageTk que es una imagen adaptada 
a Tkinter. Esta imagen es la imagen ecualizada de la imagen activa de la GUI. 
 
• Imagen_byn_global: Representa a un objeto ImageTk que es una imagen adaptada a 
Tkinter. Es la imagen en escala de grises de la imagen activa de la GUI. 
 
• Blur_img_tk_global: Representa un objeto ImageTk que es una imagen adaptada a Tkinter. 
Es la imagen activa tras ser filtrada por un filtro gaussiano.• Median_img_tk_global: Representa un objeto ImageTk que es una imagen adaptada a 
Tkinter. Es la imagen activa pasada por un filtro de mediana. 
 
• Res1_global: Representa la cadena de caracteres de la imagen en escala de grises, pero 
como conjunción de dos matrices. 
 
• Res2_global: Representa la cadena de caracteres de la imagen en escala de grises, pero 
como conjunción de dos matrices. 
 
• Blur_global. Representa la cadena de caracteres de la imagen activa tras ser filtrada por un 
filtro gausiano. 
 
• Median_global: Representa la cadena de caracteres de la imagen activa tras ser pasada por 
un filtro de mediana. 
 
• Image_1_global_contour. Representa la cadena de caracteres que conforma el contorno de 
la imagen activa dentro de la GUI. 
 
• Contours_cv2_tk_global. Representa un objeto ImageTk que es una imagen adaptada a 
Tkinter. Es la imagen que conforma el contorno de la imagen activa dentro de la GUI. 
 
• Cnts_global: Representa una matriz con los contornos de la imagen. 
 
• Alto_global: Representa al alto de la imagen recortada o de la imagen original en la GUI. 
 
• Ancho_global: Representa al ancho de la imagen recortada o de la imagen original en la 
GUI. 
 
• Alto_adaptado_global: Alto de la imagen activa adaptado a la altura de la interfaz gráfica. 
Esta variable hace que la imagen activa no sobrepase los límites de la GUI. 
 
 
Implementación en Python 
 
 
 
22 
• Ancho_adaptado_global:Ancho de la imagen activa adaptado a la anchura de la interfaz 
gráfica. Esta variable hace que la imagen activa no sobrepase los límites de la GUI. 
 
• Topx, topy, botx, boty: Coordenadas de la selección del rectángulo a la hora de recortar una 
imagen dentro de la GUI. 
 
• Rect_id_global: Representa al rectángulo que se imprime en la imagen activa que se quiere 
recortar dentro de la GUI. 
 
• Image_original_global: Representa a la imagen original adaptada al tamaño de la interfaz 
gráfica. 
 
• Canvas2_global: Representa al objeto Canvas perteneciente a Tkinter, donde se introduce 
la imagen recortada en la GUI. 
 
• Pix_global: Contiene la matriz de la imagen con la que vamos a realizar todas las 
transformaciones implantadas en la GUI. 
 
• HayRecorte: Variable con función de bandera. Cuando esta variable tiene valor ‘1’, existe 
un recorte sobre la imagen original, sin embargo, cuando vale ‘0’, la imagen original no ha 
sufrido más cambios mas allá de un cambio de escala para que esta quepa en la GUI. 
A todas estas variables le daremos un valor boolean inicial (Falso o verdadero), un entero 
(cero) o ninguno (None). 
Código: 
 
path_global = True; 
image_1_global = True; 
hsv_global = True; 
mask_global = True; 
B_global = True; 
B1_global = True; 
B2_global = True; 
magnitudFFT_global = True; 
magnitudFFT2_global = True; 
imagen_ecualizada_global = True; 
imagen_byn_global = True; 
blur_img_tk_global =True; 
median_img_tk_global=True; 
res1_global = True; 
res2_global = True; 
 
23 
 
23 Herramienta de Reconocimiento de Imágenes en Python 
 
blur_global = True; 
median_global = True; 
image_1_global_countour = True; 
contours_cv2_tk_global = True; 
cnts_global = True; 
alto_global = True; 
ancho_global = True; 
alto_adaptado_global= True; 
ancho_adaptado_global = True; 
topx, topy, botx, boty = 0, 0, 0, 0 
rect_id_global = None 
image_original_global = None 
canvas2_global = None 
pix_global = True; 
HayRecorte = 0; 
 
4.2.2 Variables locales 
Las variables locales se desclaran en su ámbito de uso (en el programa principal, y dentro de una 
función). 
Por lo tanto, debido a su definición se describirán las variables locales declaradas y definidas por el 
usuario en el programa principal o en las funciones en las que están declaradas, ya que son muchas y 
puede dar lugar a confusión. 
 
4.3 Módulo principal 
El modulo principal del programa contiene los elementos más esenciales del programa, en los que están 
incluidos todos los widgets Tkinter, que conformarán nuestra interfaz gráfica. 
Uno de ellos, el más importante, es la raíz o base de la interfaz gráfica. A partir de este widget raíz, el 
resto de widgets se van almacenando dentro de este, y así se ira dando un aspecto a la interfaz gráfica 
haciendo el widget raiz de contenedor. Recibe el nombre de “ventana1”. Le ponemos un tamaño, un 
nombre, y no dejamos que su tamaño sea modificable por el usuario (todo en las siguientes figuras). 
También se configura el color de fondo, el tipo de cursor, el contorno y el borde de este en la GUI. 
A partir de la raíz, creamos el resto de widgets necesarios para la implementación de la interfaz gráfica. 
Se crean widgets como “labeltitulo” que son etiquetas de texto. Estos elementos de la interfaz gráfica 
también se configuran para darle forma a la GUI. 
Debido a las funcionalidades de la herramienta, se ha decidido dividir la interfaz en 3 pestañas distintas 
para diferenciar la funcionalidad de cada una dentro de la interfaz. Por lo tanto, se crea un panel de 
pestañas siendo esto un tipo de element gráfico que permite dividir una parte de la ventana en distintas 
solapas llamado “cuaderno1”. Se añaden las pestañas con nombre “pagina1”, “pagina2” y “pagina3”. 
Dentro de estas pestañas, se diseñan todos los elementos que se introducen cada una de ellas. 
 
Implementación en Python 
 
 
 
24 
En la primera pestaña, se incluye “boton1_abrir”. Este botón permite al usuario introducer una imagen 
para tratar con ella. En esta misma pestaña, se introduce un objeto Canvas para una vez introducida la 
imagen por el usuario, este objeto Canvas contenga la imagen introducida por el usuario. Asimismo, 
este objeto Canvas permite seleccionar un rectangulo sobre la imagen insertada. Este objeto Canvas 
recibe el nombre de “canvas”. Se configura también un segundo botón llamado “boton2_limpiar” que 
limpiará la GUI de la imagen introducida una vez el botón sea pulsado. 
En la segunda pestaña, se incluye una lista deplegable llamada “comboLabel”, en la que están las 
siguientes opciones: 
 
• FFT. 
• Escala de grises. 
• Filtrado gaussiano. 
• Histograma. 
• Filtrado de Mediana. 
• Contorno imagen 
 
Según la opción elegida, en el widget de imagen “label20” se imprimirá la imagen correspondiente a 
la opción elegida. También existen dos botones más que son importantes: “boton3_guardar” y 
“boton5_histograma”. El primero de ellos sirve para guardar la imagen según la opción elegida, y el 
segundo sirve para imprimir un histograma relacionado con la imagen ecualizada. 
Por ultimo, en la tercera pestaña se representará la imagen contour y la visualización en 3d de la FFT 
de la imagen activa. Estas imagenes respectivamente se insertarán en los widgets “label15” y 
“label17”. 
Código: 
 
 
ventana1 = tk.Tk() 
ventana1.geometry("1200x700") 
ventana1.title("Herramienta de reconocimiento de imágenes") 
ventana1.resizable(0,0) 
 
ventana1.config(bg="#0B121D") 
ventana1.config(cursor="hand2") 
ventana1.config(relief="sunken") 
ventana1.config(bd=8) 
 
labeltitulo= Label(ventana1, text="Herramienta de reconocimiento de imágenes", padx=15,pady=15) 
labeltitulo.config(fg="white", bg="#0B121D",font=("Arial",18)) 
labeltitulo.pack(anchor=N) 
cuaderno1 = ttk.Notebook(ventana1,width=800, height=600) 
cuaderno1.place(x=200,y=50) 
 
25 
 
25 Herramienta de Reconocimiento de Imágenes en Python 
 
 
pagina1 = ttk.Frame(cuaderno1) 
cuaderno1.add(pagina1, text="Inicio", padding=10) 
 
label1 = ttk.Label(pagina1, text="Bienvenido \nInserte una imagen para tratar con ella.\n") 
label1.grid(column=0, row=0) 
boton1_abrir = ttk.Button(pagina1, text="Abrir imagen",command=choose) 
boton1_abrir.grid(column=0, row=1) 
 
canvas = tk.Canvas(pagina1) 
canvas.config(cursor="arrow") 
 
canvas.bind('<Button-1>', get_mouse_posn) 
canvas.bind('<B1-Motion>', update_sel_rect) 
 
label19 = Label(pagina1, text=None) 
label19.grid(column=0,row=4)boton2_limpiar = ttk.Button(pagina1, text="Limpiar",command=limpiar) 
boton2_limpiar.grid(column=0,row=3) 
 
pagina2 = ttk.Frame(cuaderno1) 
cuaderno1.add(pagina2, text="Tratamiento de la imagen",padding=10,state="disabled") 
comboLabel = ttk.Combobox(pagina2, values=[ "FFT", "Escala de grises", "Filtrado gaussiano", 
"Histograma", "Filtrado de Mediana", "Contorno imagen"]) 
comboLabel.current(1) 
comboLabel.bind("<<ComboboxSelected>>", imprime_label) 
comboLabel.place(x="20",y="20") 
 
label2 = ttk.Label(pagina2, text=None) 
label2.place(x="20", y="0") 
label20 = Label(pagina2, image=None) 
label20.place(x="320",y="20") 
label21 = ttk.Label(pagina2,text=None) 
label21.place(x="20", y="100") 
boton3_guardar = ttk.Button(pagina2, text="Guardar",command=save_file,state="disabled" ) 
boton3_guardar.place(x="20", y="45") 
boton5_histograma = ttk.Button(pagina2, text="Imprimir Histograma", command=histograma) 
 
Implementación en Python 
 
 
 
26 
boton5_histograma.place(x="20", y="70") 
label_histograma_titulo = Label(pagina2, text=None) 
label_histograma_titulo.place(x="20", y="175") 
label_histograma = Label(pagina2, image=None) 
label_histograma.place(x="20", y="200") 
 
pagina3 = ttk.Frame(cuaderno1) 
cuaderno1.add(pagina3, text="Contour / 3D",padding=10,state="disabled" ) 
label14 = ttk.Label(pagina3, text=None) 
label14.place(x="175", y="0") 
label15= ttk.Label(pagina3,image=None) 
label15.place(x="0", y="60") 
label16 = ttk.Label(pagina3, text=None) 
label16.place(x="15", y="550") 
label17_titulo = ttk.Label(pagina3, text=None) 
label17_titulo.place(x="550", y="0") 
label17 = ttk.Label(pagina3, image=None) 
label17.place(x="370", y="20") 
boton4_contour = ttk.Button(pagina3, text="Visualizacion 3D", command = contour_y_3d) 
boton4_contour.place(x="650", y="400") 
 
ventana1.mainloop() 
 
4.4 Funciones definidas por usuario 
4.4.1 Get_mouse_posn(event) 
Se utilizan las variables globales indicadas en la figura. 
Devuelve la posición del ratón cada vez que pase el ratón por la imagen. 
Código: 
 
def get_mouse_posn(event): 
 global topy, topx 
 topx, topy = event.x, event.y 
 
4.4.2 Update_sel_rect(event) 
Se utilizan las variables globales indicadas en la figura. 
 
27 
 
27 Herramienta de Reconocimiento de Imágenes en Python 
 
Selecciona las coordenadas del rectángulo a recortar sobre la imagen. 
Código: 
 
def update_sel_rect(event): 
 global rect_id_global 
 global topy, topx, botx, boty 
 botx, boty = event.x, event.y 
 canvas.coords(rect_id_global, topx, topy, botx, boty) 
 
4.4.3 Contour_y_3d() 
Se utilizan las variables globales indicadas en la figura. 
En esta función, al comienzo cierras las posibles ventanas de pyplot creadas con anterioridad en otras 
funciones. 
Tras esto, se crea una ventana pyplot con la figura 3D de la FFT de la imagen. 
Código: 
 
def contour_y_3d(): 
 global magnitudFFT_global 
 plt.clf() 
 plt.close() 
 x, y = magnitudFFT_global.shape 
 X = np.arange(0, x) 
 Y = np.arange(0, y) 
 xx, yy = np.meshgrid(Y, X) 
 fig2 = plt.figure() 
 ax = fig2.gca(projection='3d', facecolor="#F0F0F0") 
 ax.plot_surface(xx, yy, magnitudFFT_global, facecolor="#F0F0F0") 
 ax.contourf(xx, yy, magnitudFFT_global, zdir='x', offset=-5) 
 plt.show() 
 
 
4.4.4 Histograma() 
Se utilizan las variables globales indicadas en la figura. 
Se hace grafica un histograma sobre la imagen que procede. Esta imagen se asignará dependiendo de lo 
que valga “HayRecorte”. Si esta variable vale “0” el histograma se hará sobre la imagen original 
introducida al comienzo del programa por el usuario. Sin embargo, si esta variable vale “1” el 
histograma se realizará sobre la imagen recortada. 
Todo el procedimiento para graficar el histograma desencadena en la variable “img_histograma_label”, 
 
Implementación en Python 
 
 
 
28 
un objeto ImageTk que contiene la imagen en Tkinter del histograma a imprimir. Esta imagen se 
imprimirá en la variable “label_histograma”. 
Posteriormente, se borran las figuras creadas en pyplot. 
Código: 
 
def histograma(): 
 global HayRecorte 
 global pix_global 
 
 if HayRecorte == 0: 
 image_1_global = cv2.imread(path_global, 1) 
 if HayRecorte == 1: 
 image_1_global = pix_global 
 
 fig = plt.figure() 
 histr = cv2.calcHist([image_1_global], [0], None, [256], [0, 256]) 
 
 plt.plot(histr) 
 fig.savefig('plot.png', facecolor="#F0F0F0") 
 
 image_1_global = cv2.imread('plot.png', 1) 
 image_1_global.shape 
 image = cv2.cvtColor(image_1_global, cv2.COLOR_BGR2RGB) 
 hsv = cv2.cvtColor(image_1_global, cv2.COLOR_BGR2HSV) 
 lw_range = np.array([0, 0, 0]) 
 up_range = np.array([255, 255, 255]) 
 mask= cv2.inRange(hsv, lw_range, up_range) 
 res = cv2.bitwise_and(image, image, mask=mask) 
 
 imagen_histograma = Image.fromarray(res).resize((280, 280), Image.ANTIALIAS) 
 img_histograma_label = ImageTk.PhotoImage(imagen_histograma) 
 label_histograma.configure(image=img_histograma_label) 
 label_histograma.image = img_histograma_label 
 remove("plot.png") 
 label_histograma_titulo.configure(text="Nº total píxeles - Rango píxeles") 
 plt.close(fig) 
 
 
29 
 
29 Herramienta de Reconocimiento de Imágenes en Python 
 
4.4.5 NoRecorta() 
Se utilizan las variables globales indicadas en la figura. 
En esta función se retrocede para volver a obtener la imagen original insertada por el usuario. Por lo 
tanto, se borra el objeto “canvas2_global” donde se almacena la imagen recortada, y se procede a leer 
de nuevo la imagen. 
Esta imagen guardará en “canvas”, y sus características geométricas en “alto_global” y 
“ancho_global”. 
Código: 
 
def NoRecorta(): 
 global image_original_global 
 global canvas2_global 
 global B1_global 
 global HayRecorte 
 global ancho_global ,alto_global 
 global pix_global 
 
 HayRecorte = 0 
 img = ImageTk.PhotoImage(image_original_global) 
 canvas2_global.destroy() 
 canvas.img = img 
 canvas.create_image(0, 0, image=img, anchor=tk.NW) 
 canvas.place(x="320",y="20") 
 B1_global.configure(state="disabled") 
 data_original = image_original_global.size 
 alto_global = data_original[0] 
 ancho_global = data_original[1] 
 pix_global = np.array(image_original_global) 
 
4.4.6 Recorta() 
Se utilizan las variables globales indicadas en la figura. 
En esta función se pretende recortar a través del rectángulo seleccionado la imagen introducida por el 
usuario. Se pretende, porque si esta función es llamada sin existir ningún área seleccionada para 
recortar, esta función no hace ninguna acción dentro de la GUI. 
En esta función, una vez recortada la imagen esta se guarda en “cropped_img”. Con el matiz de que 
ahora esta imagen recortarda “cropped_img” tenemos que aumentarla para que el usuario pueda 
observarla con mayor definición, manteniendo la relación de aspecto de la imagen y no desfigurarla. 
 
 
Implementación en Python 
 
 
 
30 
Código: 
 
def Recorta(): 
 global image_1_global 
 global topy, topx, botx, boty 
 global cropped_img_label 
 global canvas2_global 
 global B1_global 
 global pix_global 
 global HayRecorte 
 global alto_global, ancho_global 
 global image_original_global 
 
 
 if topx != 0 or topy != 0 or botx != 0 or boty != 0: 
 canvas.delete("all") 
 HayRecorte = 1 
 canvas2_global = tk.Canvas(pagina1) 
 area = (topx, topy, botx, boty) 
 cropped_img = image_original_global.crop(area) 
 data1 = cropped_img.size 
 alto_global = data1[0] 
 ancho_global = data1[1] 
 if alto_global < 550 and ancho_global < 550: 
 while ancho_global < 450 and alto_global < 450: 
 alto_global = alto_global* 1.02 
 ancho_global = ancho_global * 1.02 
 cropped_img1 = cropped_img.resize((int(alto_global),int(ancho_global)),Image.ANTIALIAS) 
 cropped_img_label = ImageTk.PhotoImage(cropped_img1) 
 canvas2_global.create_image(0, 0, image=cropped_img_label, anchor=tk.NW) 
 canvas2_global.place(x="320",y="20") 
 canvas2_global.config(width=int(alto_global), height=int(ancho_global)) 
 pix_global = np.array(cropped_img) 
 image_1_global = pix_global 
 B1_global.configure(state="normal") 
 
 
 
31 
 
31 Herramienta de Reconocimiento de Imágenes en Python 
 
4.4.7 Limpiar() 
Se utilizan las variables globales indicadas en la figura. 
En esta función, las dos pestañas últimas se deshabilitan para no poder acceder a ellas, ya que se va a 
eliminar la imagen insertada a la GUI. Si existe una imagen recortada, se eliminará el objeto canvas 
“canvas2_global” que es donde se encuentra. Igualmente, se vaciarán los widgets pertenecientes a la 
primera pestaña. 
Código: 
 
def limpiar(): 
 global B_global, B1_global, B2_global 
 global canvas2_global 
 global HayRecorte 
 try: 
 cuaderno1.tab(1, state="disabled") 
 cuaderno1.tab(2,state="disabled") 
 canvas.delete("all") 
 
 if HayRecorte == 1: 
 canvas2_global.destroy() 
 
 label19.configure(text=" ") 
 label_histograma_titulo.configure(text=" ") 
 label21.configure(text=" ") 
 label_histograma.configure(image=None) 
 label_histograma.image = None 
 label20.configure(image=None, relief = None) 
 label20.image=None 
 boton3_guardar.configure(state="disabled") 
 
 B_global.destroy() 
 B1_global.destroy() 
 B2_global.destroy() 
 except AttributeError: 
 print("No hay nada que borrar") 
 
4.4.8 ReconocimientoImagen() 
Se utilizan las variables globales indicadas en la figura. 
 
Implementación en Python 
 
 
 
32 
Esta función es la función cerebro del programa y la que realiza todas las funciones relacionadas con el 
tratamiento de las imágenes. Se habilitan las 2 pestañas que estaban deshabilitadas al comienzo del 
programa. 
Dependiendo si ha habido recorte o no con anterioridad sobre la imagen insertada, se procede de una 
manera o de otra para que la variable local “image_2” y la variable global “image_1_global” hagan 
referencia al recorte o a la imagen original. 
Tras esto, se realiza a realizar transformaciones para conseguir los siguientes objetivos: 
 
• FFT de la imagen. 
• Imagen en escala de grises. 
• Filtrado gaussiano de la imagen. 
• Filtrado de Mediana sobre la imagen. 
• Imagen ecualizada 
• Contorno de los límites de la imagen 
• Contorno de la FFT (con 7 niveles) 
• Vista preliminar de la visualización 3d de la FFT. 
 
Tras realizar las transformaciones pertinentes, se borran las figuras creadas en pyplot y los archivos 
guardados. 
Código: 
 
def ReconocimientoImagen(): 
 global path_global 
 global cropped_img_global 
 global imagen_global 
 global image_1_global 
 global hsv_global 
 global mask_global 
 global magnitudFFT2_global 
 global imagen_ecualizada_global 
 global imagen_byn_global 
 global blur_img_tk_global 
 global median_img_tk_global 
 global magnitudFFT_global 
 global res1_global 
 global blur_global 
 global median_global 
 global res2_global 
 global image_1_global_countour 
 
33 
 
33 Herramienta de Reconocimiento de Imágenes en Python 
 
 global contours_cv2_tk_global 
 global cnts_global 
 global alto_adaptado_global , ancho_adaptado_global 
 global pix_global 
 global HayRecorte 
 
 cuaderno1.tab(1, state="normal") 
 cuaderno1.tab(2, state="normal") 
 
 imagen_recortada= Image.fromarray(pix_global) 
 imagen_recortada.save("Prueba.png") 
 image_2 = cv2.imread("Prueba.png", 0) 
 
 if HayRecorte == 1: 
 data_nuevo = image_2.shape 
 alto_nuevo = data_nuevo[0] 
 ancho_nuevo = data_nuevo[1] 
 while ancho_nuevo < 450 and alto_nuevo < 550 
 alto_nuevo = alto_nuevo * 1.02 
 ancho_nuevo = ancho_nuevo * 1.02 
 if HayRecorte == 0: 
 image_2 = cv2.imread(path_global, 0) 
 image_1_global = cv2.imread(path_global, 1) 
 alto_nuevo = alto_adaptado_global 
 ancho_nuevo = ancho_adaptado_global 
 f = np.fft.fft2(image_2, [256,256]) 
 fshift = np.fft.fftshift(f) 
 magnitudFFT_global = 20 * np.log(np.abs(fshift)) 
 
 magnitudFFT1_global = Image.fromarray(magnitudFFT_global).resize((350, 350), 
Image.ANTIALIAS) 
 magnitudFFT2_global = ImageTk.PhotoImage(magnitudFFT1_global) 
 gray_img = cv2.cvtColor(image_1_global, cv2.COLOR_BGR2GRAY) 
 
 hsv_global = cv2.cvtColor(image_1_global, cv2.COLOR_BGR2HSV) 
 lw_range = np.array([0, 0, 0]) 
 up_range = np.array([255, 255, 255]) 
 mask_global=cv2.inRange(hsv_global, lw_range, up_range) 
 
Implementación en Python 
 
 
 
34 
 res1_global = cv2.bitwise_and(gray_img, gray_img, mask=mask_global) 
 
 gray_img1 = Image.fromarray(res1_global).resize((int(ancho_nuevo), int(alto_nuevo)), 
Image.ANTIALIAS) 
 imagen_byn_global = ImageTk.PhotoImage(gray_img1) 
 
 blur_global = cv2.GaussianBlur(image_1_global, (5, 5), 0) 
 blur_img = 
Image.fromarray(blur_global).resize((int(ancho_nuevo),int(alto_nuevo)),Image.ANTIALIAS) 
 blur_img_tk_global= ImageTk.PhotoImage(blur_img) 
 
 median_global = cv2.medianBlur(image_1_global, 5) 
 median_img = 
Image.fromarray(median_global).resize((int(ancho_nuevo),int(alto_nuevo)),Image.ANTIALIAS) 
 median_img_tk_global = ImageTk.PhotoImage(median_img) 
 
 img_to_yuv = cv2.cvtColor(image_1_global, cv2.COLOR_BGR2YUV) 
 img_to_yuv[:, :, 0] = cv2.equalizeHist(img_to_yuv[:, :, 0]) 
 hist_equalization_result = cv2.cvtColor(img_to_yuv, cv2.COLOR_YUV2BGR) 
 res2_global = cv2.bitwise_and(hist_equalization_result, hist_equalization_result, 
mask=mask_global) 
 hist_equalization_result2 = Image.fromarray(res2_global).resize((int(ancho_nuevo), 
int(alto_nuevo)), Image.ANTIALIAS) 
 imagen_ecualizada_global = ImageTk.PhotoImage(hist_equalization_result2) 
 
 image_1_global_countour = image_1_global 
 gray = cv2.cvtColor(image_1_global_countour, cv2.COLOR_BGR2GRAY) 
 blurred = cv2.GaussianBlur(gray, (5, 5), 0) 
 thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1] 
 cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, 
 cv2.CHAIN_APPROX_SIMPLE) 
 cnts_global = imutils.grab_contours(cnts) 
 for c in cnts_global: 
 cv2.drawContours(image_1_global_countour, [c], -1, (0, 255, 0), 2) 
 contours_cv2 = Image.fromarray(image_1_global_countour).resize((int(ancho_nuevo), 
int(alto_nuevo)), Image.ANTIALIAS) 
 contours_cv2_tk_global = ImageTk.PhotoImage(contours_cv2) 
 
 label14.configure(text="Contour") 
 label17_titulo.configure(text="3D") 
 
35 
 
35 Herramienta de Reconocimiento de Imágenes en Python 
 
 lw_range1 = np.array([0, 0, 0]) 
 up_range1 = np.array([255, 255, 255]) 
 x, y = magnitudFFT_global.shape 
 X = np.arange(0, x) 
 Y = np.arange(0, y) 
 xx, yy = np.meshgrid(Y, X) 
 fig = plt.figure() 
 contorno1 = plt.contour(xx, yy, magnitudFFT_global, alpha=0.9, levels=7) 
 plt.colorbar(contorno1) 
 fig.savefig('plot.png', facecolor="#F0F0F0") 
 imagen_contour = cv2.imread('plot.png', 1) 
 hsv_global1 = cv2.cvtColor(imagen_contour, cv2.COLOR_BGR2HSV) 
 imagen_cv2_contour = cv2.cvtColor(imagen_contour, cv2.COLOR_BGR2RGB) 
 mask_global1 = cv2.inRange(hsv_global1, lw_range1, up_range1) 
 res_global1 = cv2.bitwise_and(imagen_cv2_contour, imagen_cv2_contour, mask=mask_global1)image_1_1 = Image.fromarray(res_global1).resize((400, 400), Image.ANTIALIAS) 
 img_1 = ImageTk.PhotoImage(image_1_1) 
 label15.configure(image=img_1) 
 label15.image = img_1 
 fig.clf() 
 plt.clf() 
 
 fig = plt.figure() 
 ax = fig.gca(projection='3d', facecolor="#F0F0F0") 
 ax.plot_surface(xx, yy, magnitudFFT_global, facecolor="#F0F0F0") 
 ax.contourf(xx, yy, magnitudFFT_global, zdir='x', offset=-5) 
 fig.savefig('plot.png', facecolor="#F0F0F0") 
 surface1 = cv2.imread('plot.png', 1) 
 hsv_global2 = cv2.cvtColor(surface1, cv2.COLOR_BGR2HSV) 
 surface1_cv2 = cv2.cvtColor(surface1, cv2.COLOR_BGR2RGB 
 mask_global2 = cv2.inRange(hsv_global2, lw_range1, up_range1) 
 res_global2 = cv2.bitwise_and(surface1_cv2, surface1_cv2, mask=mask_global2) 
 image_surface = Image.fromarray(res_global2).resize((350, 350), Image.ANTIALIAS) 
 img_surface = ImageTk.PhotoImage(image_surface) 
 label17.configure(image=img_surface) 
 label17.image = img_surface 
 
 remove('Prueba.png') 
 
Implementación en Python 
 
 
 
36 
 remove('plot.png') 
 fig.clf() 
 plt.clf() 
 plt.close(fig) 
 
 
4.4.9 Choose() 
Se utilizan las variables globales indicadas en la figura. 
Esta función permite interactuar por primera vez al usuario con la GUI, permitiéndole al usuario 
introducir una imagen para realizarle todas las transformaciones mencionadas anteriorimente. 
Antes de guardar la imagen en un objeto canvas, tenemos que saber las dimensiones de este objeto, pero 
sin sobrepasar una geometría determinada (450 x 550 píxeles) manteniendo siempre su relación de 
aspecto. 
Una vez se encuentra el nuevo tamaño de la imagen, la metemos en el objeto canvas llamado “canvas”. 
Se extrae información sobre la imagen original y la imprimimos en el widget “label19”. 
Se crean nuevos botones: 
• “B_global”, que llama a la función Recorta() 
• “B1_global”, que llama a la función NoRecorta() 
• “B2_global”, que llama a la función ReconocimientoImagen() 
Código: 
 
def choose() 
 global B_global, B1_global, B2_global 
 global path_global 
 global cropped_img_global 
 global imagen_global 
 global image_1_global 
 global hsv_global 
 global mask_global 
 global funcion_global 
 global res_global 
 global ancho_global, alto_global 
 global alto_adaptado_global, ancho_adaptado_global 
 global image_original_global 
 global pix_global 
 global rect_id_global 
 global HayRecorte 
 
37 
 
37 Herramienta de Reconocimiento de Imágenes en Python 
 
 global canvas2_global 
 try: 
 if HayRecorte == 1: 
 canvas2_global.destroy() 
 path_global = filedialog.askopenfilename() 
 image_1_global = cv2.imread(path_global, 1) 
 data = image_1_global.shape 
 image_original_global = cv2.cvtColor(image_1_global, cv2.COLOR_BGR2RGB) 
 hsv_global = cv2.cvtColor(image_1_global, cv2.COLOR_BGR2HSV) 
 lw_range = np.array([0, 0, 0]) 
 up_range = np.array([255, 255, 255]) 
 mask_global = cv2.inRange(hsv_global, lw_range, up_range) 
 res_global= cv2.bitwise_and(image_original_global, image_original_global, mask=mask_global) 
 alto_global = data[0] 
 ancho_global = data[1] 
 while ancho_global > 450 or alto_global > 550: 
 alto_global = alto_global * 0.9 
 ancho_global = ancho_global * 0.9 
 
 alto_adaptado_global = alto_global 
 ancho_adaptado_global = ancho_global 
 image_original_global = Image.fromarray(res_global).resize((int(ancho_global),int(alto_global)), 
Image.ANTIALIAS) 
 pix_global = np.array(image_original_global) 
 imagen_global=image_original_global; 
 img = ImageTk.PhotoImage(image_original_global) 
 canvas.img = img 
 canvas.create_image(0, 0, image=img, anchor=tk.NW) 
 canvas.place(x="320",y="20") 
 canvas.config(width=int(ancho_global), height=int(alto_global)) 
 rect_id_global = canvas.create_rectangle(topx, topy, topx, topy,dash=(2, 2), fill='', 
outline='white') 
 
 
 
 
 
Implementación en Python 
 
 
 
38 
 
 label19.configure(text="Informacion Imagen Original\nAlto: {} píxeles\nAncho: {} 
píxeles\nCanales: {} píxeles".format(data[0], data[1], data[2])) 
 B_global = Button(pagina1, text="Recortar Imagen", command=Recorta) 
 B_global.place(x=0,y=200) 
 B1_global = Button(pagina1, text="Sin recortar", command= NoRecorta,state="disabled") 
 B1_global.place(x=100,y=200) 
 
 B2_global = Button(pagina1, text="Comenzar", bg = "#F0F0F0" , 
command=ReconocimientoImagen) 
 B2_global.place(x=220, y=200) 
 rect_id_global = canvas.create_rectangle(topx, topy, topx, topy, 
 dash=(2, 2), fill='', outline='white') 
 except AttributeError: 
 print("Error tipo NoneType") 
 
 
 
 
4.4.10 Save_file() 
Se utilizan las variables globales indicadas en la figura. 
Dependiendo de la opción escogida dentro de la segunda pestaña, se guardará una imagen u otra. 
Por ejemplo, si en la segunda pestaña está escogida la opción de la FFT de la imagen, y es llamada esta 
función con el botón correspondiente, se guardará la imagen FFT en extensión .png en el directorio que 
el usuario elija. 
Código: 
 
def save_file(): 
 try: 
 global magnitudFFT_global 
 global res1_global 
 global blur_global 
 global median_global 
 global res2_global 
 global image_1_global_countour 
 
 gray_img1 = Image.fromarray(res1_global) 
 
 
39 
 
39 Herramienta de Reconocimiento de Imágenes en Python 
 
 file = filedialog.asksaveasfilename(filetypes=[("PNG",".png")],defaultextension=".png") 
 if comboLabel.get() == "FFT": 
 matplotlib.image.imsave(str(file), magnitudFFT_global) 
 
 elif comboLabel.get() == "Escala de grises": 
 gray_img1.save(str(file)) 
 
 elif comboLabel.get() == "Filtrado gausiano": 
 matplotlib.image.imsave(str(file), blur_global) 
 
 elif comboLabel.get() == "Histograma": 
 matplotlib.image.imsave(str(file), res2_global) 
 
 elif comboLabel.get() == "Filtrado de Mediana": 
 matplotlib.image.imsave(str(file), median_global) 
 
 elif comboLabel.get() == "Contorno imagen": 
 matplotlib.image.imsave(str(file), image_1_global_countour) 
 except ValueError: 
 print("No hay formato escogido") 
 
Implementación en Python 
 
 
 
40 
 
4.4.11 Imprime_label(event) 
Se utilizan las variables globales indicadas en la figura. 
Imprimirá en “label2” y en “label20” el título y la imagen correspondiente con la opción elegida dentro 
de la lista desplegable con las opciones . Por ejemplo, si la opción elegida es la FFT de la imagen, en 
“label2” aparecerá la etiqueta de texto correspondiente a la FFT, y en “label20” aparecerá la imagen 
correspondiente a la FFT. 
Código: 
 
def imprime_label(event): 
 global magnitudFFT2_global 
 global imagen_ecualizada_global 
 global imagen_byn_global 
 global median_img_tk_global 
 global contours_cv2_tk_global 
 global cnts_global 
 
 label21.configure(text=" ") 
 boton3_guardar.configure(command=save_file, 
 state="normal") # state=disabled para deshabilitar 
 if comboLabel.get() == "FFT": 
 label20.configure(image=magnitudFFT2_global) 
 label20.image = magnitudFFT2_global 
 label2.configure(text="Imagen FFT") 
 
 elif comboLabel.get() == "Escala de grises": 
 label2.configure(text="Imagen original en escala de grises") 
 label20.configure(image=imagen_byn_global) 
 label20.image = imagen_byn_global 
 
 elif comboLabel.get() == "Contorno

Continuar navegando

Materiales relacionados

136 pag.
Python para Principiantes

User badge image

pilarsimonwilliam

262 pag.
516 pag.
Python

User badge image

Alejandra Leon