herramienta de reconocimiento de imágenes en python

88
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

Upload: others

Post on 08-Jul-2022

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Herramienta de Reconocimiento de Imágenes en Python

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

Page 2: Herramienta de Reconocimiento de Imágenes en Python
Page 3: Herramienta de Reconocimiento de Imágenes en Python

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

Page 4: Herramienta de Reconocimiento de Imágenes en Python
Page 5: Herramienta de Reconocimiento de Imágenes en Python

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

Page 6: Herramienta de Reconocimiento de Imágenes en Python
Page 7: Herramienta de Reconocimiento de Imágenes en Python

vii

A mi familia

A mis amigos y compañeros

Page 8: Herramienta de Reconocimiento de Imágenes en Python
Page 9: Herramienta de Reconocimiento de Imágenes en Python

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

Page 10: Herramienta de Reconocimiento de Imágenes en Python
Page 11: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 12: Herramienta de Reconocimiento de Imágenes en Python
Page 13: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 14: Herramienta de Reconocimiento de Imágenes en Python

Í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

Page 15: Herramienta de Reconocimiento de Imágenes en Python

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

Page 16: Herramienta de Reconocimiento de Imágenes en Python
Page 17: Herramienta de Reconocimiento de Imágenes en Python

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

Page 18: Herramienta de Reconocimiento de Imágenes en Python
Page 19: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 20: Herramienta de Reconocimiento de Imágenes en Python

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

Page 21: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 22: Herramienta de Reconocimiento de Imágenes en Python

Introducción

4

Page 23: Herramienta de Reconocimiento de Imágenes en Python

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-

Page 24: Herramienta de Reconocimiento de Imágenes en Python

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

Page 25: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 26: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 27: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 28: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 29: Herramienta de Reconocimiento de Imágenes en Python

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 -

Page 30: Herramienta de Reconocimiento de Imágenes en Python

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 las matemá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

Page 31: Herramienta de Reconocimiento de Imágenes en Python

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]:

Page 32: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 33: Herramienta de Reconocimiento de Imágenes 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

Page 34: Herramienta de Reconocimiento de Imágenes en Python

Herramienta y Desarrollo en Python

16

son matrices que conforman el dimensionamiento de la matriz que compone la

imagen.

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.

Page 35: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 36: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 37: Herramienta de Reconocimiento de Imágenes en Python

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

Page 38: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 39: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 40: Herramienta de Reconocimiento de Imágenes en Python

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;

Page 41: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 42: Herramienta de Reconocimiento de Imágenes en Python

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)

Page 43: Herramienta de Reconocimiento de Imágenes en Python

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)

Page 44: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 45: Herramienta de Reconocimiento de Imágenes en Python

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”,

Page 46: Herramienta de Reconocimiento de Imágenes en Python

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)

Page 47: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 48: Herramienta de Reconocimiento de Imágenes en Python

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")

Page 49: Herramienta de Reconocimiento de Imágenes en Python

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.

Page 50: Herramienta de Reconocimiento de Imágenes en Python

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

Page 51: Herramienta de Reconocimiento de Imágenes en Python

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)

Page 52: Herramienta de Reconocimiento de Imágenes en Python

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")

Page 53: Herramienta de Reconocimiento de Imágenes en Python

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')

Page 54: Herramienta de Reconocimiento de Imágenes en Python

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

Page 55: Herramienta de Reconocimiento de Imágenes en Python

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')

Page 56: Herramienta de Reconocimiento de Imágenes en Python

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)

Page 57: Herramienta de Reconocimiento de Imágenes en Python

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")

Page 58: Herramienta de Reconocimiento de Imágenes en Python

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 imagen":

label20.configure(image=contours_cv2_tk_global)

label20.image = contours_cv2_tk_global

label2.configure(text="Contorno imagen original")

label21.configure(text="Número de Contour: " + str(len(cnts_global)))

elif comboLabel.get() == "Histograma":

Page 59: Herramienta de Reconocimiento de Imágenes en Python

41

41 Herramienta de Reconocimiento de Imágenes en Python

label20.configure(image=imagen_ecualizada_global)

label20.image = imagen_ecualizada_global

label2.configure(text="Imagen histograma ecualizada")

elif comboLabel.get() == "Filtrado de Mediana":

label20.configure(image=median_img_tk_global)

label20.image = median_img_tk_global

label2.configure(text="Imagen filtrada por mediana")

elif comboLabel.get() == "Filtrado gaussiano":

label20.configure(image=blur_img_tk_global)

label20.image = blur_img_tk_global

label2.configure(text="Imagen filtrada gaussiana")

Page 60: Herramienta de Reconocimiento de Imágenes en Python

Implementación en Python

42

Page 61: Herramienta de Reconocimiento de Imágenes en Python

43

5 COMPILACIÓN GUI

5.1 Introducción

Compilar es reunir o juntar en un mismo volumen un conjunto de partes o extractos de distintos

documentos que tienen un tema en común [18].

En el ámbito de la Informática, la compilación es la fase de codificación en que un programa es pasado

y traducido del código fuente (lenguaje de alto nivel) al código máquina. Podemos distinguir en esta

etapa, al menos, cuatro fases:

Figura 5. Fases de la compilación.

• Análisis léxico: Extrae del archivo Fuente todas las cadenas de caracteres que reconoce como

parte del vocabulario y genera un conjunto de tokens como salida. Si no es posible, se

generarán los mensajes de error correspondientes [19].

Figura 6. Análisis léxico.

• Análisis sintáctico: Se procesa la secuencia de tokens generada con anterioridad, y se construye

una representación intermedia que permite al compilador realizar su labor [19].

Page 62: Herramienta de Reconocimiento de Imágenes en Python

Compilación GUI

44

Figura 7. Análisis sintáctico.

• Análisis semántico: Se utiliza el árbol generado en la fase previa para detector posibles

violaciones a la semántica del lenguaje de programación [19].

• Generación de Código. Se transforma todo lo anterior en lenguaje máquina (Código objeto).

Muy importante la optimización del Código para esta fase [19].

Este proceso, es realizado por un compilador virtual, cuya tarea consiste en llevar un programa fuente a

programa objeto.

5.2 PyInstaller

Módulo que ayudará para generar archivos ejecutables en Python.

Genera un ejecutable “.exe” en Windows, un “.dmg” en MAC o el ejecutable que utilice el Sistema

Operativo. Dentro del ejecutable se incluye el propio intérprete de Python, y por ello se podrá utilizer el

ejecutable en cualquier ordenador sin necesidad de instalar Python ni ninguna de sus librerías utilizadas

en el programa original [20].

Se compila igual para cualquier SO, solo que creará distintos tipos de ejecutables dependiendo del SO

en el que nos encontremos. Por ejemplo, para Windows creará un archivo con extension “.exe”.

Si se importan las librerías necesarias dentro del script, PyInstaller incluirá los recursos y módulos

necesarios que se haya en el programa de forma automática.

Page 63: Herramienta de Reconocimiento de Imágenes en Python

45

45 Herramienta de Reconocimiento de Imágenes en Python

La instalación es muy sencilla, abriendo el “Símbolo del Sistema” y escribiendo:

Figura 8. Instalación PyInstaller.

PyInstaller es muy poderoso, pero tiene algunas complicaciones. Admite la creación de ejecutables para

Windows, Linux y macOS, pero no una compilación cruzada. Es decir, no permite la ejecución de un

ejecutable dirigido a un sistema operativo desde otro sistema operativo distinto. Por lo tanto, para

distribuir ejecutables para múltiples tipos de SO, necesitará una máquina de compilación para cada SO

soportado [25].

El trabajo, generalmente, seguirá las líneas siguientes [25]:

• Crear scrip a usar.

• Instalar PyInstaller.

• Ejecutar PyInstaller para compilar.

• Probar el ejecutable.

5.2.1 Compilación programa

La compilación de un archivo programa en Python sigue siendo muy sencillo.

Tan solo tienes que escribir el siguiente comando de la figura en “Símbolo del Sistema”, justo en la ruta

en la que se encuentre nuestro archivo .py.

En este ejemplo, nuestro programa en Python a convertir en ejecutable sería “hola.py”, y solo generaría

un archivo ejecutable conteniendo todo.

El ejecutable se guardará en una carpeta llamada “dist”, que estará ubicada en el mismo directorio

donde se encuentre nuestro script a compilar.

Figura 9. Compilación programa en Python.

Page 64: Herramienta de Reconocimiento de Imágenes en Python

Compilación GUI

46

Page 65: Herramienta de Reconocimiento de Imágenes en Python

47

6 RESULTADOS DE LA GUI

Figura 10. Inicio de la GUI.

Page 66: Herramienta de Reconocimiento de Imágenes en Python

Resultados de la GUI

48

Figura 11. Introducción de la imagen a tratar.

Page 67: Herramienta de Reconocimiento de Imágenes en Python

49

49 Herramienta de Reconocimiento de Imágenes en Python

Figura 12. Inicio con la imagen introducida.

Page 68: Herramienta de Reconocimiento de Imágenes en Python

Resultados de la GUI

50

Figura 13. Inicio con la selección del área recortada sobre la imagen.

Page 69: Herramienta de Reconocimiento de Imágenes en Python

51

51 Herramienta de Reconocimiento de Imágenes en Python

Figura 14. Inicio con recorte de la imagen.

Page 70: Herramienta de Reconocimiento de Imágenes en Python

Resultados de la GUI

52

Figura 15. Tratamiento de la imagen, FFT.

Page 71: Herramienta de Reconocimiento de Imágenes en Python

53

53 Herramienta de Reconocimiento de Imágenes en Python

Figura 16. Tratamiento de la imagen, escala de grises.

Page 72: Herramienta de Reconocimiento de Imágenes en Python

Resultados de la GUI

54

Figura 17. Tratamiento de las imágenes, filtrado gaussiano.

Page 73: Herramienta de Reconocimiento de Imágenes en Python

55

55 Herramienta de Reconocimiento de Imágenes en Python

Figura 18. Tratamiento de la imagen, imagen ecualizada e histograma.

Page 74: Herramienta de Reconocimiento de Imágenes en Python

Resultados de la GUI

56

Figura 19. Tratamiento de la imagen, filtrado de mediana.

Page 75: Herramienta de Reconocimiento de Imágenes en Python

57

57 Herramienta de Reconocimiento de Imágenes en Python

Figura 20. Tratamiento de la imagen, contornos.

Page 76: Herramienta de Reconocimiento de Imágenes en Python

Resultados de la GUI

58

Figura 21. Guardar imagen tratada seleccionada.

Page 77: Herramienta de Reconocimiento de Imágenes en Python

59

59 Herramienta de Reconocimiento de Imágenes en Python

Figura 22. Contour y vista preliminar 3D de la FFT.

Page 78: Herramienta de Reconocimiento de Imágenes en Python

Resultados de la GUI

60

Figura 23. Visualización 3D de la FFT.

Page 79: Herramienta de Reconocimiento de Imágenes en Python

61

61 Herramienta de Reconocimiento de Imágenes en Python

Figura 24. Inicio, limpieza de imagen

Page 80: Herramienta de Reconocimiento de Imágenes en Python

Resultados de la GUI

62

Page 81: Herramienta de Reconocimiento de Imágenes en Python

63

7 CONCLUSIONES Y LÍNEAS FUTURAS

Este trabajo ha supuesto poner en práctica, no solo mucho de lo aprendido durante el Grado, sino además

estudiar cada una de las librerías implementadas para alcanzar los objetivos con una GUI. Comenzando desde

el reconocimiento y el procesado de cada uno de los píxeles de las imágenes, hasta su misma programación e

implementación en Python. Es una mezcla de conocimientos, pero quiero hacer una especial mención a la

conexión directa que se hace en el trabajo entre dos de las intensificaciones del Grado, como son Telemática

(referencia a todo lo relacionado con la programación en Python: programación, módulos, compilación…) y

Sonido e Imagen (trabajo con imágenes y transformaciones). Esto ha hecho que, sumado a mi mención

Sistemas de Telecomunicación, los conocimientos sobre las distintas áreas que también maneja las

telecomunicaciones que tenía han incrementado.

Durante la realización del trabajo han ido surgiendo problemas y dificultades que he sabido resolver

en poco tiempo. Estas dificultades no eran sencillas de resolver, pero por ello Python es un lenguaje de

programación tan usado. Estas dificultades en la mayoría de las veces las he podido resolver navegando por

Internet, y encontrando siempre una solución que ya esta predefenida en algún modulo o librería. Distintas

dificultades como redimensionar la imagen introducida por el usuario, posicionar correctamente distintos

widgets que forman parte de la GUI, compilación correcta de un programa implementado en Python 3.8 …

todas ellas, se han resuelto dedicándole unas horas a navegar por Internet y revisando distintos foros sobre

Python.

Este trabajo también me ha servido para aprender a desarrollar un proyecto de trabajo desde el

principio hasta el final de este. Al principio del trabajo, tenía una idea en la cabeza mucho más sencilla de lo

que iba a ser el trabajo. Con el paso de las semanas, esta idea ha ido cogiendo forma, ha ido añadiendo nuevos

estilos y nuevas funcionalidades que han deparado en una GUI completa.

Me ha servido para saber a lo que me puedo encontrar en un futuro, a realizar un trabajo complejo y

que este se complique en ciertos momentos. Saber controlar los momentos en los que las cosas no salen como

uno quiere, y encontrar el momento y la forma para seguir adelante en una tarea. Creo que esto en el futuro me

ayudará a desempeñar distintas tareas bajo tensión.

Cabe destacar que este lenguaje de programación no era nuevo para mí, pero nunca lo llegue a ver tan

profundamente. Esto suponía un reto que a comienzo de curso no sabía como sería. En este sentido, si que

tenía una gran motivación para poder aprender a programar en uno de los lenguajes de programación más

importantes del mundo.

Con vistas hacia el futuro, aquí van una serie de posibles mejoras para poder expandir la interfaz

gráfica para hacerla aún más usable para el público:

• Añadir más funcionalidades: más filtrados tanto lineales como no liales sobre la imagen o la porción

de la imagen seleccionada sobre la imagen original. Estas funcionalidades se programarían en el

fichero principal Trabajo_UltimoAvance.py, y sería una buena idea añadir una o varias opciones en la

lista desplegable de la segunda pestaña para que el usuario pueda seleccionar la transformación sobre

la imagen que desee.

• Ampliar la GUI: más pestañas dentro de la GUI. Por ejemplo, crear una nueva pestaña dentro de la

Page 82: Herramienta de Reconocimiento de Imágenes en Python

Conclusiones y Líneas futuras

64

GUI para que el usuario pueda interactuar con la imagen, girando la imagen o haciendo un recorte

sobre ella con alguna figura curva. También en estas pestañas se podría crear una sección para tocar

algún área relacionada con las imágenes.

• Cambiar el diseño de la GUI: se puede cambiar el diseño de la GUI, de forma que el ingeniero que lo

haga mejore la interacción GUI-usuario.

Tras ver cuales son las posibles líneas de mejora del trabajo, algunos detalles para tener en cuenta si se

quiere continuar con el desarrollo de la Herramienta son:

• El código está descrito en el capítulo titulado “Implementación en Python”. En este capítulo están

definidas todas las variables globales, las variables locales y las funciones definidas usadas en el

programa. Además, está el cuerpo del programa, que es el bloque fundamental del trabajo. Con

copiar todo el código en una IDE e instalar las librerías descritas en el capítulo titulado “Software

y diseño” el software funcionará a la perfección. Para ampliarlo, sólo se tendrá que

modificar/añadir las funciones del programa.

• Respecto a la compilación, con PyInstaller se podrá compilar el programa en cualquier SO. Eso

sí, solo se podrá utilizar en el SO en el que se compile. Por ejemplo, si se compila en Windows y

produce un ejecutable “.exe”, este ejecutable sólo será usable en Windows.

Page 83: Herramienta de Reconocimiento de Imágenes en Python

65

65 Herramienta de Reconocimiento de Imágenes en Python

Page 84: Herramienta de Reconocimiento de Imágenes en Python

66

REFERENCIAS

[1] Covantec R.L., « Programación en Python - Nivel básico », 2018. [En línea]. Available:

https://entrenamiento-python-basico.readthedocs.io/es/latest/leccion1/introduccion.html

[2] OpenWebinars S.L.,« Qué es Python: Características, evolución y futuro », 2020. [En línea]. Available:

https://openwebinars.net/blog/que-es-python/

[3] JetBrains s.r.o., « PyCharm », 2020. [En línea]. Available: https://www.jetbrains.com/es-es/pycharm/

[4] OpenCV team, 2020. [En línea]. Available: https://opencv.org/about/

[5] NumPy, 2020. [En línea]. Available: https://numpy.org/

[6] SciPy developers, 2020. [En línea]. Available: https://www.scipy.org/about.html

[7] Wikipedia, la enciclopedia libre, « Tkinter », 2020. [En línea]. Available:

https://es.wikipedia.org/wiki/Tkinter

[8] The Matplotlib development team, 2018. [En línea]. Available: https://matplotlib.org

[9] Uniwebsidad, « Python para principiantes », 2020. [En línea]. Available:

https://uniwebsidad.com/libros/python/capitulo-10/modulos-de-sistema

[10] Universitat de Barcelona, « El filtrado de imágenes ». [En línea]. Available:

http://www.ub.edu/pa1/node/filtrado

[11] Wkipedia, la enciclopedia libre, « Scipy », 2019. [En línea ]. Available:

https://es.wikipedia.org/wiki/SciPy

[12] Wikilibros, libros libres para un mundo libre, « Python », 2016. [En línea]. Available:

https://es.wikibooks.org/wiki/Python/Interfaz_gr%C3%A1fica_con_Tkinter

[13] Wikipedia, la enciclopedia libre, « Interfaz gráfica de usuario », 2020. [En línea]. Available:

https://es.wikipedia.org/wiki/Interfaz_gr%C3%A1fica_de_usuario

[14] Mclibre, «Introducción a la programación con Python », 2020. [En línea]. Available:

https://www.mclibre.org/consultar/python/lecciones/python-variables.html

[15] GeeksforGeeks, «Python OpenCV». [En línea]. Available: https://www.geeksforgeeks.org/python-

opencv-cv2-cvtcolor-method/

[16] Paradigma, «¿Es Python el lenguaje del futuro? », 2018. [En línea]. Available:

https://www.paradigmadigital.com/dev/es-python-el-lenguaje-del-futuro/

Page 85: Herramienta de Reconocimiento de Imágenes en Python

67

67 Herramienta de Reconocimiento de Imágenes en Python

[17] Pythones, « Crear, guardar y ejecutar scripts de Python », 2020. [En línea]. Available:

https://pythones.net/archivos-py-crear-guardar-y-ejecutar-scripts-de-python/

[18] Significados, « Significado de Compilación », 2020. [En línea]. Available:

https://www.significados.com/compilacion/

[19] López Vega, Jeder, « Análisis y diseño de algoritmos: El proceso de compilación ». [En línea].

Available:

http://libroweb.alfaomega.com.mx/book/477/free/ovas_statics/lec_adicionales/Compiladores.pdf

[20] Hector Costa, « PyInstaller » , 2019. [En línea]. Available:

https://docs.hektorprofe.net/python/distribucion/pyinstaller/

[21] Recursos Python, 2020. [En línea]. Available: https://recursospython.com/guias-y-manuales/instalar-pil-

pillow-efectos/

[22] Covantec R.L., « Funciones», 2018. [En línea]. Available: https://entrenamiento-python-

basico.readthedocs.io/es/latest/leccion5/funciones.html

[23] Python, «Servicios genéricos del sistema operativo: os », 2020. [En línea]. Available:

https://docs.python.org/2/library/os.html

[24] LinuxAdictos. [En línea]. Available: https://www.linuxadictos.com/breve-aclaracion-sobre-los-entornos-

graficos-libres.html

[25] Real Python, « Uso de PyInstaller para distribuir fácilmente aplicaciones de Python », 2020. [En línea].

Available: https://realpython.com/pyinstaller-python/#limitations

Page 86: Herramienta de Reconocimiento de Imágenes en Python

Referencias

68

Page 87: Herramienta de Reconocimiento de Imágenes en Python

69

GLOSARIO

FFT: Transformada Rápida de Fourier

3D: Tres Dimensiones

SO: Sistema Operativo

GUI: Interfaz Gráfica de Usuario

3D: Entorno de Desarrollo Integrado

API: Interfaz de Programación de Aplicaciones

Page 88: Herramienta de Reconocimiento de Imágenes en Python

Glosario

70