Documentos de Académico
Documentos de Profesional
Documentos de Cultura
PROCESOS Y APLICACIONES
AUTOR
BEATRIZ BORRELLA PETISCO
CODIRECTORES
D. ANTONIO LÓPEZ MONTES (UCM)
D. NICOLÁS ANTEQUERA RODRÍGUEZ (UCM)
D. ANTONIO MARTÍNEZ RAYA (UNED/UPM)
Por otro lado, quiero agradecer a mis tutores el trabajo realizado. A Antonio López, por
aceptar trabajar conmigo en este TFG desde el primer momento y conseguir darme
soluciones a todos los problemas que le iba planteando. A Nicolas, por todo el esfuerzo y
trabajo, por darme la idea inicial y por el aprendizaje recibido. Y a Antonio Martínez, por
su atenta lectura del trabajo y todas las mejoras y correcciones recibidas.
Finalmente, mi agradecimiento a todos los amigos que me han acompañado estos cuatro
años, sin ellos esto hubiera sido mucho más complicado y aburrido.
Resumen
La visión artificial es una disciplina cuyo principal objetivo es procesar y analizar
imágenes del mundo real, con la finalidad de que estas puedan ser entendidas y tratadas
por un ordenador. El concepto de visión artificial surgió en la década de los sesenta del
siglo pasado. Desde entonces ha ido ganando importancia y funcionalidades hasta
convertirse hoy en día en uno de los mejores métodos de identificación de imágenes. La
principal aplicación de la visión artificial es el reconocimiento de patrones y es utilizada
en campos como la vigilancia y la seguridad, el reconocimiento facial y el funcionamiento
de sistemas robóticos.
El elemento básico y principal de la visión artificial es el píxel, es decir, cada una de las
partes que forman una imagen digital. En rasgos generales, la visión artificial consiste en
una serie de operaciones matemáticas sobre los píxeles de la imagen, que varían
dependiendo de lo que se quiera conseguir en cada momento. Estas operaciones reciben
el nombre de filtros y se realizan a través de máscaras.
The basic and main element of computer vision is the pixel, that is, each of the parts that
make up a digital image. In general terms, computer vision consists of a series of
mathematical operations on the pixels of the image, which vary depending on what is to
be achieved at any given time. These operations are called filters and are performed
through masks.
In this work we will begin with a theoretical introduction to computer vision, studying in
detail the components and stages of the process that is carried out. Subsequently, we will
put this process into practice with three different case studies. The final objective will be
to be able to create an artificial vision process from the moment a photograph is taken
until the computer is able to understand the elements that form that image.
Dedicatoria ................................................................................................................................... 2
Agradecimientos .......................................................................................................................... 3
Resumen ....................................................................................................................................... 4
Abstract ........................................................................................................................................ 5
Índice de Contenidos ................................................................................................................... 6
1. Introducción a la Visión Artificial ......................................................................................... 7
1.1 Definición y Evolución histórica ...................................................................................... 7
1.2 Conceptos preliminares sobre la visión artificial ........................................................... 8
1.3 ¿Qué es una imagen digital? ............................................................................................. 9
1.4 Fase de pre-procesamiento del sistema de visión artificial .......................................... 13
1.4.1 Filtros espaciales ....................................................................................................... 13
1.4.2 Filtrado espectral...................................................................................................... 18
1.5 Fase de Segmentación del Sistema de Visión Artificial................................................ 21
1.6 Fase de interpretación del sistema de visión artificial ................................................. 28
2. Casos prácticos ...................................................................................................................... 29
2.1 Procesos de tratamiento de imágenes ............................................................................ 29
2.1.1 Pre-procesamiento de las imágenes ........................................................................ 29
2.1.2 Segmentación ............................................................................................................ 34
2.2 Detección de círculos en una imagen ............................................................................. 40
2.2.1 Programa básico ....................................................................................................... 40
2.2.2 Aplicación al juego del tres en raya ........................................................................ 43
2.3 Detección de objetos en una imagen .............................................................................. 46
2.3.1 Objetivo y funcionamiento ...................................................................................... 46
2.3.2 Procedimiento ........................................................................................................... 47
3. Conclusiones: debilidades y fortalezas de la visión artificial ............................................ 51
Referencias ................................................................................................................................. 54
Apéndice A – Código de los programas de procesamiento de imágenes .............................. 56
A.1 Procesos de pre-procesamiento y segmentación en imágenes .................................... 56
A.1.1 Pre-procesamiento ................................................................................................... 56
A.1.2 Segmentación ........................................................................................................... 58
A.2 Detección de círculos en una imagen ............................................................................ 60
A.2.1 Programa básico ...................................................................................................... 60
A.2.2 Aplicación al juego de tres en raya ........................................................................ 61
A.3 Detección e identificación de objetos en una imagen .................................................. 64
1. Introducción a la Visión Artificial
1.1 Definición y Evolución histórica
La visión artificial es una disciplina científica que incluye métodos para adquirir, procesar
y analizar imágenes del mundo real con el fin de producir información que pueda ser
tratada por una máquina. Es una aplicación de la teórica clásica de matrices a dimensiones
considerablemente grandes. Su objetivo principal es la deducción automática de la
estructura y propiedades de un mundo tridimensional a partir de una o varias imágenes
bidimensionales [1].
En comparación con la visión humana, ofrece una mejor evaluación de las magnitudes
físicas y un mayor desempeño en las tareas rutinarias. Algunas de sus múltiples
aplicaciones están relacionadas con la vigilancia y la seguridad, el reconocimiento facial,
la programación de vehículos autónomos o el funcionamiento de sistemas robóticos
mano-ojo [1].
Por otro lado, tenemos la cámara. Este dispositivo utiliza un juego de lentes y un sensor
que recibe la luz reflejada por la escena y permite generar imágenes. La lente se utiliza
para transmitir luz al sensor de una forma controlada y así poder tener una imagen
enfocada de uno o varios objetos. Los sensores en una cámara son componentes sensibles
a la luz que modifican su señal eléctrica en función de la intensidad luminosa que perciben
[4].
Siguiendo con los componentes que forman el sistema de visión artificial tenemos el
sistema de procesamiento, que recibe las imágenes e implementa funciones dependiendo
del tipo de análisis que haya que realizar. El sistema de procesamiento está formado a su
vez por tres componentes. En primer lugar, la tarjeta de adquisición, que permite transferir
la imagen de la cámara a la memoria de la computadora. Por otro lado, los algoritmos de
procesado, conocidos como la parte inteligente del sistema y que aplican las
trasformaciones necesarias y las extracciones de información de las imágenes capturadas.
Y finalmente, la interfaz, que, una vez realizado el procesamiento de la imagen, es la
encargada de mostrar los resultados obtenidos [4].
Por último, tenemos que mencionar los actuadores externos. Se trata del conjunto de
elementos que muestran los resultados obtenidos del procesamiento de la imagen y
pueden ser robots, monitores, dispositivos neumáticos e hidráulicos, autómatas
programables, etc [4].
En los próximos apartados desarrollaremos las partes más importantes de este proceso
Cada uno de los puntos de una imagen digital recibe el nombre de píxel. Cada píxel se
identifica por la fila y la columna a la que pertenece. Gráficamente tienen la siguiente
estructura:
Figura 1.1: Estructura de una imagen digital [7]
Un píxel cuantifica la intensidad de la imagen en ese punto y, por tanto, posee un valor
numérico. Al color negro se le asocia el valor 0 y al color blanco el valor 2𝑛 − 1, siendo
𝑛 el número de cortes diferentes [7]. Por ejemplo, si 𝑛 = 4, entonces 𝑛𝑒𝑔𝑟𝑜 = 0 y
𝑏𝑙𝑎𝑛𝑐𝑜 = 2 ∗ 4 − 1 = 15, lo que significa que consideramos 15 intensidades
diferentes de gris. Cuanto mayor sea 𝑛 mayor será la homogeneidad de la imagen.
Los píxeles también influyen en otras características de la imagen. Por un lado, varía la
resolución espacial o nitidez de la imagen, que mejora cuanto más elevado es el número
de píxeles. Por otro lado, la resolución en amplitud o tonalidades de gris diferentes, que
será mayor cuantos más niveles de gris haya [7].
Figura 1.3: Consecuencias del número de niveles de gris en una imagen [8]
Las imágenes a las que hemos hecho referencia son monocromáticas, es decir, solo tienen
una banda de color, que es el gris. Sin embargo, generalmente trabajamos con imágenes
multiespectrales, estas imágenes son una función con tantas componentes como bandas
tenga la imagen [7]. Se definen como:
Las imágenes en color que vemos en nuestro día a día tienen tres bandas que dependen
del espacio de color, el más conocido es el RGB (Red, Green, Blue) [7]:
Figura 1.4: Esquema de una imagen en color descompuesta en cada uno de sus planos [7].
Otro concepto asociado a las imágenes y que debemos tener en cuenta ya que nos va a ser
útil a la hora del pre-procesamiento son las máscaras digitales o filtros.
Una vez establecido el concepto de vecindad podemos introducir las máscaras digitales.
Las máscaras digitales, también conocidas como ventanas, filtros o plantillas, son
matrices de tamaño reducido donde cada coeficiente (𝑥, 𝑦) corresponde a un píxel. Son
generalmente cuadradas y todas las que utilizaremos en este trabajo serán de tamaño 3x3.
En cada una de las entradas de la matriz encontramos un coeficiente, 𝑤𝑖 , cuyo valor
dependerá de la máscara que estemos utilizando [7].
𝐶 = ∑(𝑧𝑖 ∗ 𝑤𝑖 ) = 𝑧1 ∗ 𝑤1 + ⋯ + 𝑧9 ∗ 𝑤9
𝑖=1
El resultado de la operación se le asigna al punto central del vecindario
Para comenzar centraremos el estudio en los filtros espaciales. En este amplio grupo
podemos diferenciar dos tipos de filtros, los lineales que explicaremos a continuación y
los no lineales que veremos más adelante. Los filtros lineales reciben este nombre porque
los valores de intensidad de los píxeles dentro de la región de procesamiento se combinan
de manera lineal para generar el píxel resultado [6]. Dentro de los filtros lineales cabe
destacar los filtros de suavizado. Su principal objetivo es suavizar la imagen, es decir,
reducir las variaciones de intensidad entre píxeles vecinos y eliminar el ruido. Esto
consiste en modificar los píxeles cuyo nivel de intensidad es muy diferente al de sus
vecinos [6]. Dentro de los filtros de suavizado vamos a estudiar los tres tipos de filtros
más conocidos y utilizados que son el filtro Box, el filtro de las medias y el filtro
Gaussiano.
Figura 1.8: El filtro para suavizado Box: a) Función tridimensional, b) Función bidimensional y
c) mascara que implementa el filtro [6]
Como podemos ver en la imagen este filtro parece una caja, de ahí su nombre, y afecta de
manera uniforme a cada píxel de la imagen ya que todos los coeficientes tienen el mismo
valor. Sin embargo, este filtro presenta unos bordes muy agudos, lo que hace que a pesar
de su sencillez sea un filtro poco recomendable [6].
Siguiendo la idea del filtro Box aparece el filtro de la media. Este filtro consiste en
reemplazar el valor de cada píxel por la media de los valores de los pixeles vecinos [9].
Un ejemplo de mascara 3x3 para este filtro seria la siguiente:
Figura 1.9: Ejemplo de mascara 3x3 para el filtro de la media
Este filtro presenta el mismo problema que el anterior y es que reduce muy bien el ruido,
pero a la vez difumina mucho los bordes de los objetos [9].
Intuitivamente parece más razonable darle mayor peso al píxel central ya que es del que
más información queremos conservar y menor peso a los pixeles vecinos. Atendiendo a
este razonamiento aparece el filtro Gaussiano. En esencia, el filtro Gaussiano corresponde
a la función de Gauss bidimensional y discreta dada por la fórmula [6]:
1 𝑥 2 +𝑦 2
−
𝐺𝜎 (𝑥, 𝑦) = 𝑒 2𝜎2
2𝜋𝜎 2
Figura 1.10: Filtrado Gaussiano. (a) Función tridimensional, (b) Función bidimensional y (c)
mascara Gaussiana que implementa el filtro [6]
El elemento central del filtro representa el peso máximo que participa en la combinación
lineal de la operación, mientras que los demás coeficientes tienen menor influencia según
estos se alejan del centro del filtro. Una de las propiedades más relevantes de este filtro
es que es invariante a las rotaciones, y en comparación con el filtro Box y el filtro de la
media es mejor opción cuando el objetivo principal es mantener los bordes de los objetos
de la imagen. Esto se debe a que este filtro permite suavizar las regiones en donde los
valores de intensidad son homogéneos sin diluir de forma tan notable los bordes.
Aunque el filtro de Gauss consiga suavizar la imagen sin degradar por completo
estructuras como puntos, líneas o bordes, es imposible aplicar filtros de suavizado lineales
y mantener estas estructuras intactas. Es aquí donde aparecen los filtros no lineales. Su
principal característica es que permiten resolver este problema de una mejor forma que el
filtro de Gauss utilizando para ello operaciones no lineales [6]. Los filtros no lineales
también calculan el resultado de un determinado píxel en la posición (𝑥, 𝑦) utilizando una
determinada región relativa a la imagen original. Dentro de estos filtros no lineales los
más sencillos son los filtros máximos y mínimos [9] y se basan en las siguientes
ecuaciones:
Donde 𝑅(𝑥, 𝑦) representa la región relativa a la posición (𝑥, 𝑦) definida por el filtro que
generalmente es un rectángulo 3x3 [6]. Veamos en la siguiente imagen el funcionamiento
de estos filtros:
Figura 1.11: Efecto del filtro mínimo sobre diferentes formas locales en una imagen [6]
En esta figura vemos la imagen original arriba y el resultado obtenido por la operación
filtro abajo. El valor A describe el ancho del filtro utilizado que también define al mismo
tiempo la región R abarcada por él. En la imagen a) vemos representado un escalón que
debido a la operación del filtro es desplazado hacia la derecha A unidades. Por otro lado,
en la imagen b) la anchura de la línea contenida en la imagen es menor a la de A y por
tanto, esta desaparece por efecto del filtro [6].
El último filtro no lineal que vamos a ver es el filtro de la mediana. Este filtro basa su
cálculo en una medida de rango en un conjunto ordenado de datos, de manera que un dato
con un valor muy grande o muy pequeño en comparación al valor del resto de datos de la
región de interés 𝑅(𝑥, 𝑦) no influirá significativamente en el resultado final [6]. La
manera de actuar de este filtro es visitar cada píxel de la imagen y reemplazar su valor
por la mediana de los píxeles vecinos [9]. Considerando que 𝑥1 , 𝑥2 , … , 𝑥𝑛 son los datos
de una muestra ordenada crecientemente, en el caso que n sea par la mediana de esa
muestra se define como:
𝑀𝑒 = 𝑥𝑛+1
2
𝑥𝑛 + 𝑥𝑛+1
2 2
𝑀𝑒 =
2
Dejando a un lado los filtros espaciales, centramos ahora el estudio en el filtrado espectral.
Su objetivo, al igual que el de los filtros anteriores es eliminar elementos que no son de
interés para el estudio. Este tipo de filtros se basan en la idea de que una imagen se puede
representar como la suma de dos componentes con diferentes escalas espaciales, por un
lado, la versión de la imagen con las bajas frecuencias y por otro lado la de la imagen con
las frecuencias altas [10]. En términos generales una señal unidimensional se puede
descomponer en un conjunto infinito de señales de tipo seno con diferentes frecuencias,
amplitudes y fases. El primer componente representa la amplitud media de la señal y tiene
frecuencia igual a 0, el siguiente componente (componente fundamental) presenta la
misma frecuencia que la señal original. Los demás componentes van adquiriendo
frecuencias sucesivamente superiores y se denominan armónicos. A medida que se
añaden componentes, la suma se aproxima cada vez más a la señal original, aunque
necesitamos infinitos componentes para que la suma sea exacta. Esta suma total de
componentes recibe el nombre de Serie de Fourier de la función original [10].
Podemos entender una imagen digital como una señal discreta bidimensional, de forma
que su serie de Fourier es una suma finita de senos y cosenos que formará la imagen
original cuando sumemos todos los términos. La suma parcial de las primeras
componentes es la formada por las frecuencias más bajas y producirá una versión de la
imagen parecida al aplicar un filtro de paso-bajo a la imagen original. De la misma forma
la suma de los últimos términos de la serie con frecuencias superiores generará una
versión de la imagen con altas frecuencias o parecida a aplicar un filtro de paso-alto [10].
La transformada de Fourier de una función continua viene dada por la siguiente expresión:
∞
𝐹(𝑢) = ∫ 𝑓(𝑥) ∗ 𝑒 −2𝜋𝑖𝑢𝑥 𝑑𝑥
−∞
Ambas funciones existen siempre que 𝑓(𝑥) sea continua e integrable y que 𝐹(𝑢) sea
integrable [10].
[10].
A continuación, vemos gráficamente el funcionamiento de estos filtros:
Por último, veamos unas imágenes de ejemplo para comprender la información que nos
da este tipo de filtros.
Figura 1.13: Ejemplo de tres imágenes con sus respectivas transformadas [10]
Aquí podemos ver tres distribuciones espaciales distintas y el efecto que provocan en la
representación en forma de imagen de su transformada, teniendo en cuenta también el
componente direccional de las frecuencias [10]. En la primera imagen vemos varias
parcelas agrícolas de distintos cultivos, lo que provoca una gran cantidad de altas
frecuencias en varias direcciones. Por otro lado, la segunda imagen quiere representar un
paisaje dunar, en la que observamos una orientación dominante NE (Norte, Este) – SO
(Sur, Oeste) debido a la acción de los vientos. Por su parte, la transformada aparece en
forma de nube, debido a que existe poca definición en la orientación dominante, no
podemos decidir si es NE o SO. En la última imagen vemos una zona oceánica con
bastantes corrientes en forma helicoidal. Esto hace que su transformada presente, por un
lado, una serie de manchas próximas al origen, correspondientes a las altas frecuencias,
y por otro, unas manchas más ligeras y difuminadas en los bordes, que corresponden a las
bajas frecuencias.
Uno de los casos más simples para detectar objetos, sin entrar todavía en la detección de
bordes, es la binarización de la imagen. Es decir, definimos un umbral llamado T y damos
el valor 0 (negro) o 255 (blanco) a cada píxel dependiendo si el valor de dicho píxel es
mayor o menor que nuestro umbral T. Siendo 𝑓(𝑥, 𝑦) cada uno de los píxeles de la imagen
un ejemplo sería:
Este procedimiento es muy eficaz cuando queremos identificar el número de objetos que
hay sobre un fondo blanco, por ejemplo, funciona muy bien a la hora de detectar el
número y palo de una baraja de cartas o la posición de las fichas en un tablero del tres en
raya o incluso en un tablero de ajedrez. Para el resto imágenes con más colores o formas
en el fondo antes de poder identificar directamente los objetos tenemos que aplicar
técnicas de detección de bordes.
El caso más básico es la detección de bordes binaria. Para empezar, tenemos que binarizar
la imagen con la técnica explicada anteriormente y después, se procesan primero las filas
de arriba a abajo y de izquierda a derecha haciendo para cada píxel [8]:
Se procede de igual forma para las columnas y se realiza la misma asignación. Una vez
tengamos las dos imágenes estas se operan mediante la operación “OR” y se obtiene la
imagen binaria de borde.
El problema aparece cuando añadimos más niveles de gris. En este caso se usan las
derivadas direccionales (gradiente espacial) u operadores de primera derivada, que
consiste en detectar las regiones de transición brusca de intensidad mediante
diferenciación espacial [7]. El gradiente de una imagen en cualquier punto se define como
un vector bidimensional dado por la siguiente ecuación [7]:
𝜕 𝑓(𝑥+∆𝑥)−𝑓(𝑥−∆𝑥)
𝐺𝑥 𝑓(𝑥, 𝑦)
𝜕𝑥 2∆𝑥
𝐺[𝑓(𝑥, 𝑦)] = [𝐺 ] = [ 𝜕 ] = [𝑓(𝑦+∆𝑦)−𝑓(𝑦−∆𝑦)]
𝑦 𝑓(𝑥, 𝑦)
𝜕𝑦 2∆𝑦
𝐺𝑦
Magnitud: |𝐺| = √𝐺𝑥 2 + 𝐺𝑦 2 Dirección: 𝜑(𝑥, 𝑦) = tan−1 𝐺
𝑥
Al obtener el gradiente de una imagen podemos obtener los bordes de esta con el método
binario que hemos explicado antes de la forma:
Una vez que hemos obtenido el gradiente, utilizamos los operadores de primera derivada
para obtener el valor del píxel que se evalúa con una relación de un umbral determinado
[7]. Su tarea, al igual que la del gradiente, es eliminar el ruido de la foto y así hacer
desaparecer bordes falsos. Algunos de estos operadores son el de Sobel, el de Prewitt y
el de Roberts. Comenzaremos estudiando los operadores de Sobel y de Prewitt ya que son
bastante similares. Como hemos explicado anteriormente, estos filtros calculan el
gradiente de la imagen en cada píxel, lo que permite encontrar el mayor aumento de los
píxeles claros a los oscuros y la tasa de cambio. El borde puede definirse como un
conjunto de posiciones de píxeles contiguos en los que se produce un cambio repentino
de los valores de intensidad en el píxel [11]. En ambos casos el algoritmo de estos
operadores consta de dos máscaras 3x3, una para el gradiente horizontal 𝐺𝑥 y otra para el
gradiente vertical 𝐺𝑦 y son las siguientes:
• Operador de Sobel
• Operador de Prewitt:
𝐺𝑥 = ( 𝑧3 + 𝑧6 + 𝑧9 ) − (𝑧1 + 𝑧4 + 𝑧7 )
𝐺𝑦 = ( 𝑧7 + 𝑧8 + 𝑧9 ) − (𝑧1 + 𝑧2 + 𝑧3 )
Su funcionamiento es idéntico al operador de Sobel
Ambos operadores son prácticamente iguales y ofrecen unos resultados muy similares.
La única diferencia que podemos encontrar en la práctica es que el operador de Sobel es
ligeramente más sensible a los bordes diagonales que el de Prewitt [6].
𝐺𝑥 = 𝑧6 − 𝑧8
𝐺𝑦 = −𝑧1 + 𝑧5
Este operador es bueno ante bordes diagonales, además, ofrece buenas prestaciones en
cuanto a localización. Sin embargo, su gran inconveniente es que es extremadamente
sensible al ruido y, por tanto, en algunos casos, la detección de bordes es muy pobre [12]
Veamos a continuación una tabla resumen con las máscaras de cada uno de los filtros
explicados.
Operador Filtros
Sobel −1 0 1 −1 −2 −1
𝐺𝑥 = [−2 0 2] 𝐺𝑦 = [ 0 0 0]
−1 0 1 1 2 1
Prewitt −1 0 1 −1 −1 −1
𝐺𝑥 = [−1 0 1] 𝐺𝑦 = [ 0 0 0]
−1 0 1 1 1 1
Roberts 0 0 0 −1 0 0
𝐺𝑥 = [0 0 1] 𝐺𝑦 = [ 0 1 0]
0 −1 0 0 0 0
Tabla 1.1: Resumen de los principales filtros de detección de bordes. Fuente: elaboración propia.
Los filtros más utilizados en la práctica y los que utilizaremos posteriormente en este
trabajo son los explicados anteriormente. Sin embargo, es importante conocer los filtros
de segunda derivada. La técnica que utilizan se basa en encontrar los pasos por cero, es
decir, la transición de positivo a negativo o viceversa. Esto lo podemos estimar a partir
de la segunda derivada [6]. Partimos de la definición de derivada para una función
unidimensional:
𝜕𝑓
= 𝑓(𝑥 + 1) − 𝑓(𝑥)
𝜕𝑥
𝜕𝑓 2
= 𝑓(𝑥 + 1) − 2𝑓(𝑥) + 𝑓(𝑥 − 1)
𝜕𝑥 2
Como hemos comentado anteriormente, el objetivo es encontrar el paso por cero del valor
del gradiente en cualquier dirección. Para ello vamos a utilizar el operador Laplaciano
que se define como:
2
𝜕 2 𝐼(𝑥, 𝑦) 𝜕 2 𝐼(𝑥, 𝑦)
∇ 𝐼(𝑥, 𝑦) = +
𝜕𝑥 2 𝜕𝑦 2
𝜕 2 𝐼(𝑥, 𝑦)
= 𝐼(𝑥 + 1, 𝑦) − 2𝐼(𝑥, 𝑦) + 𝐼(𝑥 − 1, 𝑦)
𝜕𝑥 2
𝜕 2 𝐼(𝑥, 𝑦)
= 𝐼(𝑥, 𝑦 + 1) − 2𝐼(𝑥, 𝑦) + 𝐼(𝑥, 𝑦 − 1)
𝜕𝑦 2
Por tanto, sustituyendo estas dos ecuaciones en la expresión del Laplaciano quedaría:
0 1 0
1 -4 1
0 1 0
Por último, veamos otro mecanismo que nos puede aportar bastante información acerca
de la imagen e incluso de sus bordes u objetos que la forman. Hablamos en este punto de
los histogramas de las imágenes. Estos son una representación gráfica de los valores de
todos los píxeles de la imagen. En el eje x se comienza con el valor 0 correspondiente al
negro y a la derecha se representa el valor máximo correspondiente al blanco. Si la imagen
es en color se representan los histogramas de los tres valores de rojo, verde y azul. El
histograma nos permite analizar la imagen según la distribución de grises ya que si hay
valores muy próximos a 0 (resp. último valor) será una imagen oscura (resp. clara).
Además, si el rango de valores del histograma es grande, la imagen tendrá un contraste
alto, mientras que si este es pequeño entonces el contraste será bajo. También nos permite
diferenciar el número de objetos y el tamaño de estos [7]. Algunos histogramas de
ejemplo son:
Figura 1.17: Ejemplo de histogramas según la iluminacion [7]
Figura 1.19: Ejemplo de histograma con dos objetos bien diferenciados [7]
1.6 Fase de interpretación del sistema de visión artificial
Una vez que hemos procesado la imagen pasamos al último paso que es el reconocimiento
e interpretación de esta. El análisis de imágenes es un proceso que consiste en descubrir,
identificar y comprender los patrones relevantes en el rendimiento de un trabajo basado
en imágenes. Además, tiene como objetivo dotar a la máquina de una capacidad de
aproximación similar a la de los humanos [13].
Todas las figuras e imágenes que veremos a continuación son de elaboración propia y el
código utilizado en los programas está basado en la referencia: [6]
Figura 2.1: Imagen de muestra para la elaboración de este caso práctico. Fuente: obtenido del
enlace https://www.agromatica.es/el-cultivo-de-girasoles/
Figura 2.2: Imagen a escala de grises obtenida por el software MATLAB a partir de la figura
2.1.
A partir de la foto en escala de grises comenzamos con el pre-procesamiento de la imagen.
Vamos a empezar aplicando algunos filtros de suavizado. El objetivo de estos filtros es
eliminar el ruido de la imagen. Aplicamos un filtro estándar que toma la misma
proporción de cada píxel vecino, este es el conocido como filtro de la media explicado
anteriormente y usaremos la máscara:
1 1 1 1
∗ [1 1 1 ]
9
1 1 1
Por otro lado, vamos a aplicar el filtro de Gauss con una máscara Gaussiana 3x3 que tiene
la estructura
1 1 2 1
∗ [2 4 2]
16
1 2 1
Figura 2.3: Comparativa entre el filtro estándar y el filtro Gaussiano, obtenida por del software
MATLAB a partir de la figura 2.2
Vemos que ambos filtros suavizan los bordes de la imagen, siendo más intenso el filtro
que toma el promedio de los pixeles externos ya que el filtro gaussiano le da más peso al
píxel central y por tanto es más suave.
Sin embargo, la verdadera utilidad de estos filtros aparece cuando tenemos una fotografía
con ruido. Vamos a aplicar ruido a la imagen para poder aplicarle después los filtros de
suavizado y comprobar que estos de verdad funcionan. El filtro más fácil de aplicar
manualmente es el de tipo sal y pimienta. Para ello convertimos aleatoriamente 500
píxeles de la imagen en un píxel de color blanco y otros 500 píxeles en color negro
Una vez tenemos la imagen con ruido le aplicamos los filtros anteriores a esta imagen y
obtenemos lo siguiente:
Figura 2.5: Comparativa entre el filtro estándar y el filtro Gaussiano en una imagen con ruido
artificial. Obtenida por el software MATLAB a partir de la figura 2.2
Vemos que con estos filtros no podemos mejorar mucho la imagen, el problema es que la
cantidad de ruido añadida es excesiva. Probamos entonces con un ruido artificial menos
brusco. Además, como se ve que el filtro estándar es mas efectivo vamos a probar con
máscaras de distinto tamaño de este tipo de filtro, en primer lugar, utilizamos una máscara
3x3 y en segundo lugar una máscara 9x9, los resultados son los siguientes:
Figura 2.6: Imagen con filtrado artificial menos brusco y el efecto sobre ella de los filtros
estándar con distinto tamaño de máscaras. Obtenido por el software MATLAB a partir de la
figura 2.1
Vemos que en este caso el filtro estándar con mascara 3x3 es capaz de suavizar el ruido
considerablemente bien. Por otro lado, el filtro estándar con mascara 9x9 hace
desaparecer por completo el ruido, sin embargo, difumina demasiado los bordes.
Hasta ahora el ruido ha sido introducido por nosotros de manera artificial, sin embargo,
ahora vamos a trabajar con una imagen con un ruido más natural.
Figura 2.8: Comparativa entre el filtro estándar y el filtro Gaussiano en una imagen con ruido
natural. Obtenida por el software MATLAB a partir de la figura 2.7
Aquí ya podemos ver que partimos de una imagen con bastante ruido natural y al aplicar
los filtros es muy notable el suavizado que se produce en la imagen, sobre todo con el
filtro estándar.
En este caso vamos a probar también con algún filtro de tipo no lineal para ver como
funcionan. Los filtros no lineales que vamos a utilizar son el filtro de máximo y mínimo.
El resultado es el siguiente:
Figura 2.9: Comparativa entre en filtro máximo y mínimo en una imagen con ruido natural.
Obtenida por el software MATLAB a partir de la figura 2.7
Podemos observar como se aclara y se oscurece la imagen dependiendo del tipo de filtro
utilizado.
2.1.2 Segmentación
Una vez que ya hemos filtrado las imágenes podemos pasar a la segunda parte del proceso
que es la que conocemos como segmentación. Aquí centraremos todos nuestros esfuerzos
en la detección de bordes y la identificación de distintos objetos. Para identificar objetos
con distinta intensidad de color el método más simple y en ocasiones, el más efectivo es
la detección de bordes binaria. Para ello vamos a definir un nivel de umbral y le damos el
color blanco a los píxeles que sobrepasen ese umbral y el color negro a los que no lo
alcancen. Para la imagen de los girasoles tomamos un umbral de 140.
Figura 2.10: Ejemplo de binarización de una imagen. Obtenida por el software MATLAB a partir
de la figura 2.1
Al ser una imagen con muchas tonalidades de gris es complicado conseguir detectar todos
los pétalos de la flor. Sin embargo, en el momento en el que tomamos una imagen de
ciertos objetos apoyados en una mesa, vemos que este filtro es muy práctico para poder
diferenciarlos, un ejemplo sería el siguiente:
Figura 2.11: Ejemplo de binarización de una imagen. Obtenida por el software MATLAB.
Fuente: elaboración propia.
Debemos tener cuidado con la sombra que nos ha quedado en la esquina inferior izquierda
para no confundirla con otro objeto, pero se pueden ver claramente los cuatro objetos
distintos que hay en la imagen.
Ahora pasaremos a aplicar los filtros de detección de bordes comenzando con el filtro de
Sobel. El procedimiento que vamos a seguir es aplicar las dos mascaras correspondientes
al filtro de Sobel, Gx en horizontal y Gy en vertical. Posteriormente calculamos el vector
gradiente y normalizamos este valor. Con eso ya obtendremos la imagen final con los
bordes detectados. Veamos imágenes del proceso para la foto del girasol.
Figura 2.12: Ejemplo de proceso de aplicación del filtro de Sobel. Obtenida por el software
MATLAB a partir de la figura 2.2
Ahora vamos a aplicar el método para una imagen con muchos bordes y vemos que
funciona igual de bien.
Figura 2.13: Ejemplo de aplicación del filtro de Sobel. Obtenida con MATLAB a partir de la
imagen disponible en el enlace https://www.sandradavidson.com/wp-
content/uploads/2021/03/selling-a-house-after-probate.jpg
En este caso hemos aplicado el filtro de Sobel paso a paso. Hay una función en MATLAB
que al proporcionarle una imagen aplica el filtro de Sobel directamente, u otros como el
filtro de Prewitt. Vamos a utilizar esta función de MATLAB para hacer una comparación
entre estos dos filtros de detección de bordes.
Figura 2.14: Comparativa entre el filtro de Sobel y el filtro de Prewitt. Obtenida por el software
MATLAB a partir de la figura 2.13
Podemos ver que los bordes que nos devuelve esta función son más agresivos que los que
hemos obtenido al principio. Esto se debe a que en el primer caso hemos normalizado la
imagen final y, sin embargo, en el segundo caso no lo estamos haciendo. También vemos
que la diferencia entre ambos filtros es prácticamente insignificante ya que los dos
cumplen bien con su objetivo.
Por último, vamos a estudiar los histogramas de las imágenes. En muchos casos los
histogramas nos permiten diferenciar el número de objetos distintos que hay. Veamos
algún ejemplo con una imagen que tiene unos colores bien diferenciados
Figura 2.15: Ejemplo de histograma de una imagen. Obtenido con el software MATLAB a partir
del enlace https://media.istockphoto.com/id/1186867446/es/vector/sem%C3%A1foro-colores-
icono-vectorial-sobre-fondo-blanco.webp?s=612x612&w=is&k=20&c=e0BoTwKHfLzYh6-
ZHtL9oIMd-hfiFoypdW3d0lzF6-A=
Como podemos ver la información que nos da el histograma es clara, aparecen cinco
colores distintos, y nos informa también de la cantidad en la que estos aparecen. Es fácil
identificar que la primera barra corresponde al color negro, el fondo de la imagen. La
segunda barra corresponde a la estructura del semáforo y las otras barras restantes
corresponden a los tres colores distintos del semáforo ya que vienen en la misma
proporción.
En el histograma de la imagen podemos ver un color que predomina sobre el resto y que
suponemos que será el tono de gris correspondiente al azul del fondo. Además, en esta
imagen hemos añadido el histograma acumulativo que parece indicar que la imagen tiene
dos claras tonalidades ya que da un salto muy pronunciado alrededor del valor 120.
Otras operaciones que podemos realizar sobre la imagen y que se van a ver reflejadas en
los histogramas son un aumento de contraste o de iluminación. Comenzamos aplicando
un aumento de contraste:
Figura 2.17: Ejemplo del efecto en el histograma de una imagen al aplicar un aumento de
contraste. Obtenida por el software MATLAB a partir de la figura 2.2
Apreciamos que los tonos claros se hacen más claros y aparecen tonos blancos, es decir,
el histograma queda desplazado a la derecha.
Figura 2.18: Ejemplo del efecto en el histograma de una imagen al aplicar un aumento de
iluminación. Obtenida por el software MATLAB a partir de la figura 2.2
2.2 Detección de círculos en una imagen
2.2.1 Programa básico
En este capítulo vamos a construir un programa en MATLAB [14] que nos permita
detectar los círculos que hay en una imagen, sin importar el color de estos.
El objetivo es ser capaces de detectar todos los círculos, es decir, conocer la posición en
la que se encuentra cada uno de ellos y el número total sin importar que unos estén encima
de otros o incluso estén cortados por los bordes de la imagen.
• Centro: da la coordenada del centro de cada círculo detectado en forma (𝑥, 𝑦).
• Radio: estimación del radio de cada círculo detectado.
Antes de aplicar esta función tenemos que saber si el parámetro ‘ObjectPolarity’ es dark
o bright, para ello pasamos la imagen a escala de grises obteniendo:
Figura 2.20: Imagen en escala de grises. Obtenida por el software MATLAB a partir de la figura
2.19
Vemos que por lo general los círculos son más oscuros, entonces aplicamos la función
con el parámetro ‘ObjectPolarity’ como dark y obtenemos la siguiente imagen:
Figura 2.21: Imagen resultante al aplicar función imfincircles con el parámetro ‘ObjectPolarity’
como dark. Obtenida por el software MATLAB a partir de la figura 2.19
Como vemos en esta imagen hemos conseguido detectar todos los círculos excepto los
amarillos. Los parámetros de rango de radio y precisión los hemos ido variando hasta
obtener la imagen anterior.
Sin embargo, todavía nos falta detectar los círculos amarillos, para ello cambiamos el
parámetro ‘ObjectPolarity’ a bright, de esta forma detectamos únicamente los círculos
amarillos.
Figura 2.21: Imagen resultante al aplicar función imfincircles con el parámetro ‘ObjectPolarity’
como bright. Obtenida por el software MATLAB a partir de la figura 2.19
Por último, necesitamos combinar ambas detecciones para tener todos los círculos.
Finalmente obtendríamos la imagen siguiente, el recuento total de círculos, los centros de
cada uno de los círculos detectados y el radio de estos.
Figura 2.22. Imagen que consigue detectar todos los círculos de la imagen. Numero de círculos
totales y coordenadas del centro y radio de cada uno de ellos. Obtenida por el software MATLAB
a partir de la figura 2.19
2.2.2 Aplicación al juego del tres en raya
Una de las aplicaciones de este tipo de detección de círculos aparece cuando queremos
enseñar a una inteligencia artificial como jugar al juego del tres en raya. Para que esta
pueda realizar los movimientos primero tiene que entender el tablero del que
generalmente obtendrá una imagen para procesarla. Es en este punto donde entra esta
aplicación de la visión artificial. Lo que queremos conseguir en este capítulo es que dada
una imagen, podamos extraer la información que hay en ella de forma que sea
comprensible por un ordenador. Vamos a partir de una imagen cualquiera en la que
tenemos un tablero de nueve casillas con fichas en forma circular de dos colores
diferentes, correspondiendo cada color a cada uno de los dos jugadores enfrentados.
Figura 2.23: Disposición del tablero de tres en raya. Imagen obtenida a partir del software
Draw.io
En este caso es bastante obvio que los círculos a detectar son más oscuros que el color de
fondo, en cualquier caso, transformamos la imagen a escala de grises para generalizar el
proceso por si acaso en algún momento cambia el color de fondo de la imagen.
Obtenemos la siguiente imagen:
Figura 2.24: Imagen del tablero de tres en raya en escala de grises. Obtenida por el software
MATLAB a partir de la figura 2.23
Vemos claramente que los colores de los círculos son más oscuros que el fondo de la
imagen, por tanto, usamos la función imfindcircles con 'ObjectPolarity' como 'dark. De
esta manera la función encuentra todos los círculos de la siguiente forma:
Figura 2.25: Detección de los círculos que forman el tablero del tres en raya. Obtenida por el
software MATLAB a partir de la figura 2.23
A partir de esta imagen podemos ver que el programa es capaz de detectar todos los
círculos, además nos devuelve el centro de cada uno de los círculos que ha detectado:
Figura 2.26: Coordenadas del centro de cada uno de los círculos detectados en el tablero.
Obtenida por el software MATLAB a partir de la figura 2.23
Por último, para obtener la información de manera que el ordenador pueda procesarla
vamos a dar la salida en forma de una matriz 3x3. Cada entrada de la matriz corresponde
con cada una de las casillas del tablero, además en los coeficientes de la matriz
encontramos un 1 si la ficha que hay es de color azul, si hay un 2 la ficha es de color rojo
y si hay un 0 todavía no hay ninguna ficha en esa casilla. Para el tablero inicial con el que
hemos empezado el ejemplo, la salida del programa sería la siguiente:
Figura 2.27: Salida del programa que detecta todos los círculos del tablero. Obtenida por el
software MATLAB a partir de la figura 2.23
A continuación, veremos otras configuraciones distintas del tablero para comprobar que
el programa funciona para cualquier número de fichas y distribuciones de estas.
• Ejemplo tablero 1
Figura 2.28: Ejemplo de disposición de tablero y salida del programa que detecta los círculos.
Obtenido por el software MATLAB a partir de la imagen creada por el software Draw.io
• Ejemplo tablero 2
Figura 2.29: Ejemplo de disposición de tablero y salida del programa que detecta los círculos.
Obtenido por el software MATLAB a partir de la imagen creada por el software Draw.io
• Ejemplo tablero 3
Figura 2.30: Ejemplo de disposición de tablero y salida del programa que detecta los círculos.
Obtenido por el software MATLAB a partir de la imagen creada por el software Draw.io
En ella podemos ver cinco objetos distintos, empezando por la parte superior y de
izquierda a derecha tenemos un ratón, una llave, una calculadora, una goma de borrar y,
por último, un bolígrafo.
El filtro de Wiener entra dentro del grupo de los filtros lineales óptimos y de forma
general, consiste en una señal de entrada 𝑥(𝑛), una respuesta deseada 𝑑(𝑛), y un filtro
lineal de respuesta impulsional ℎ(𝑛). Este filtro es alimentado por 𝑥(𝑛) y produce una
salida 𝑦(𝑛). La diferencia entre la señal de salida del filtro 𝑦(𝑛) y la señal deseada 𝑑(𝑛)
es el error de estimación 𝑒(𝑛). El objetivo de este filtro es conseguir que el error 𝑒(𝑛)
sea, en un sentido estadístico, lo más pequeño posible. Para ello se utiliza la minimización
del valor cuadrático medio del error [17]:
ξ = {|𝑒(𝑛)|2 }
Las imágenes que obtenemos tras el pre-procesamiento son las siguientes:
El siguiente paso es binarizar la imagen, tomando un umbral, en este caso 0.45, le damos
el color blanco a los pixeles con un valor inferior al umbral seleccionado y el color negro
a los pixeles con un valor superior. Esto lo realizamos con la función im2bw y la imagen
que obtenemos es la siguiente:
Figura 2.33: Binarizacion de la imagen. Obtenida por el programa MATLAB a partir de la figura
2.32
Sin embargo, con esta imagen todavía no podemos detectar los diferentes objetos ya que
tenemos que seguir eliminando ruido. El proceso que queremos llevar a cabo es
homogeneizar las regiones en las que haya un objeto, contabilizarlas y calcular algunas
de sus medidas, pero si hacemos zoom sobre alguno de los objetos, como por ejemplo, la
llave, vemos que hay regiones más pequeñas que no pertenecen a la región principal de
la propia llave.
Figura 2.34: Regiones a eliminar o unificar. Obtenida a partir de MATLAB a partir de la figura
2.33
Estas regiones nos van a dar problemas, por lo que tenemos que eliminarlas o unificarlas
a la imagen central. Vamos a hacer ambas cosas. En primer lugar, eliminamos las regiones
de píxeles que tengan menos de 130 píxeles con la función bwareaopen y posteriormente
rellenamos los espacios en negro que hay entre las regiones principales de los objetos y
las regiones pequeñas que lo rodean con la función imclose. Obtenemos el siguiente
resultado:
Figura 2.35: Eliminacion de las regiones que generan problemas. Obtenida por el software
MATLAB a partir de la figura 2.33
Aquí ya no tenemos regiones perdidas, por tanto, podemos identificar las que pertenecen
a objetos distintos. Para ello lo que hacemos es detectar los bordes de las regiones en
blanco usando la función bwboundaries y le asignamos un color diferente a cada una de
las distintas regiones encontradas. Obtenemos la imagen:
Figura 2.36: Identificación de las regiones de los diferentes objetos. Obtenida por el software
MATLAB a partir de la figura 2.35
El último paso es calcular los parámetros que nos van a permitir identificar qué objetos
son. Para ello utilizamos la función regionprops que calcula el área y el centro de cada
región identificada. Por otro lado, gracias a la función boundary que calculaba los bordes
podemos obtener el perímetro. Con todas estas medidas vamos a calcular una métrica
dada por la fórmula:
4 ∗ 𝜋 ∗ 𝑎𝑟𝑒𝑎
𝑚𝑒𝑡𝑟𝑖𝑐𝑎 =
𝑝𝑒𝑟𝑖𝑚𝑒𝑡𝑟𝑜 2
Finalmente, añadimos este valor a la imagen cerca de la región que está midiendo y
obtenemos:
Figura 2.37: Métricas asociadas a las regiones de cada objeto. Obtenida por el software
MATLAB a partir de la figura 2.36
Estos valores también los podemos obtener en un vector que será el que le pasaremos al
ordenador. Como anteriormente le habremos asignado a cada tipo de objeto su métrica
correspondiente, el ordenador ya será capaz de identificar el número y el tipo de objetos
de la imagen.
Tras una breve introducción a la visión artificial, el concepto mejor interiorizado es que
la visión artificial pretende que, dada una imagen, un ordenador sea capaz de procesarla
y entender los elementos que hay en ella. Uno de los campos en los que los sistemas de
visión artificial han supuesto grandes mejoras es la automatización de la industria, en
concreto, es claro el ejemplo de las cadenas de producción. Un sistema de visión artificial
es capaz de inspeccionar miles de piezas por minuto, además, si este sistema se ha
construido con una resolución de cámara óptima, puede inspeccionar detalles de objetos
que son demasiado pequeños para la vista humana. Otra ventaja es que permite eliminar
el contacto físico entre el sistema de prueba y la pieza a evaluar, lo que evita posibles
daños y costes de mantenimiento de los componentes mecánicos [18].
Por otro lado, una aplicación que se utiliza en comercios, aeropuertos e incluso, nuestras
casas, son los sistemas de videovigilancia. La visión artificial, gracias al reconocimiento
facial, permite detectar personas no reconocidas, sospechosas e incluso delincuentes en
busca y captura. Pero los sistemas de vigilancia no solo se limitan al reconocimiento de
personas. Esta vigilancia puede estar orientada en sistemas de asistencia en quirófanos y
hospitales. En estos casos vigila los procedimientos y puede alertar si hay pacientes en
riesgo o alguna desviación en el procedimiento quirúrgico [19].
Finalmente, dentro de las aplicaciones que he encontrado más llamativas se encuentra la
capacidad de comprensión que tienen los sistemas de visión artificial. Las máquinas
tienen una mayor capacidad para gestionar y comprender conceptos complejos. Algunos
ejemplos concretos son el proyecto “InnerEye” de Microsoft Research Cambridge que
busca facilitar la comprensión de la forma que tiene un tumor cerebral, o el proyecto
“Triton”, un software de Gauss Surgical, con el que se trata de estimar la pérdida de
sangre durante una cesárea [19].
Son claras las numerosas ventajas que nos proporciona la visión artificial. Sin embargo,
debemos tener en cuenta algunas de sus limitaciones y debilidades. Para empezar, como
hemos comentado al principio, la visión artificial encuentra serios problemas a la hora de
identificar conceptos complejos no estructurados. A lo largo de los últimos años esta
tecnología ha levantado muchas polémicas debido a reconocimientos erróneos. Algunos
ejemplos son etiquetar a personas de raza negra como orangutanes o basarse en la
vestimenta y el origen étnico para catalogar a una persona como un riesgo [19]. Es aquí
donde nos damos cuenta de que es necesario seguir desarrollando estas tecnologías,
mejorando los métodos de entramiento y ampliando los ejemplos con los que se
construyen estos sistemas.
Por otro lado, un trabajo futuro muy interesante sería partir de uno de los casos prácticos
realizados en este trabajo, en concreto, el de la identificación del tablero de tres en raya.
El objetivo sería construir una inteligencia artificial que aprenda a jugar a este juego.
Podría tratarse, por ejemplo, de un brazo robótico, que sería el encargado de la parte
mecánica del juego, es decir, de realizar el movimiento de las fichas. El aprendizaje se
llevaría a cabo mediante una red neuronal. A esta red neuronal podríamos entrenarla
mediante métodos de aprendizaje supervisado. Para empezar, podríamos pasarle algunas
jugadas de ejemplo para que sepa el movimiento que tiene que hacer dependiendo de la
estructura de tablero que encuentre. Posteriormente, la dejaríamos jugando con otra
máquina ya entrenada o con cualquier persona, recibiendo una “recompensa” cuando sea
capaz de ganar la partida y un “castigo” cuando pierda. El objetivo final será crear una
máquina que haya aprendido a jugar al tres en raya desde cero y sea capaz de ganar
siempre, o al menos, no perder.
Referencias
[1] Contaval, “¿Qué es la visión artificial y para qué sirve?,” Deteccion Blog, 2016.
https://www.contaval.es/que-es-la-vision-artificial-y-para-que-sirve/ (accessed Sep. 05,
2022).
[5] J. Molleda Meré, “Técnicas de visión por computador para la reconstrucción en tiempo
real de la forma 3D de productos laminados,” Universidad de Oviedo, 2008.
[6] E. Cuevas, D. Zaldívar, and M. Pérez, Procesamiento digital de imágenes con MATLAB
y Simulink, 1st ed. Mexico: RA-MA, 2010.
[9] R. C. González and R. E. Woods, Digital Image Processing, 3a. Pearson Prentice Hall,
2008.
[10] R. A. Schowengerdt, Remote Sensing: Models and Methods for Image Processing.
Academic Press, 1997.
[11] S. Hadri, “Image Processing Best Practices — C++ Part 2,” Medium, 2020.
https://soubhihadri.medium.com/image-processing-best-practices-c-part-2-
c0988b2d3e0c
[12] L. Sáez Acosta, “Detección de bordes en una imagen.” Universidad de Jaén, 2015.
[Online]. Available: https://docplayer.es/4877825-Deteccion-de-bordes-en-una-
imagen.html
[13] E. García-Meléndez, “Módulo VII : Sistemas de Información Geográfica y
Teledetección, análisis visual de imágenes.” Escuela de Negocios (EOI), 2007.
[19] M. Salas, “Visión artificial y personas: cuando el roce hace el cariño,” BBVA Next
Technologies, 2021. https://www.bbvanexttechnologies.com/pills/vision-artificial-y-
personas-cuando-el-roce-hace-el-carino/ (accessed Sep. 05, 2022).
Apéndice A – Código de los programas de
procesamiento de imágenes
A.1 Procesos de pre-procesamiento y segmentación en imágenes
A.1.1 Pre-procesamiento
%Pre-procesamiento
%Comenzamos leyendo la imagen
A=imread('C:\Users\34684\Documents\TFG\MATLAB\practica2\objetos.jpeg')
;
%medimos su tamaño
[m,n] = size(A);
%Segunda parte:
%Vamos a aplicar distintos filtros de suavizado
%Filtro 1:
%Filtro 3x3 que suaviza la imagen utilizando el promedio de los
pixeles
%vecinos
[m n] = size(Ag);
Ag = double(Ag);
Agr = Ag;
for r = 2:m-1
for c = 2:n-1
Agr(r,c) = 1/9*(Ag(r-1,c-1)+Ag(r-1,c)+Ag(r-1,c+1)+...
Ag(r,c-1)+Ag(r,c)+Ag(r,c+1)+Ag(r+1,c-1)+...
Ag(r+1,c)+Ag(r+1,c+1));
end
end
Agr = uint8(Agr);
imshow(Agr)
title('Imagen filtro estandar')
%Filtro 2:
%Filtro de Gauss utilizando la mascara Gaussiana 3x3
Agg = Ag;
for r = 2:m-1
for c = 2:n-1
Agg(r,c) = 1/16*(Ag(r-1,c-1)+2*Ag(r-1,c)+Ag(r-1,c+1)+...
2*Ag(r,c-1)+4*Ag(r,c)+2*Ag(r,c+1)+Ag(r+1,c-1)+...
2*Ag(r+1,c)+Ag(r+1,c+1));
end
end
Agg = uint8(Agg);
imshow(Agg)
title('Imagen filtro gaussiano')
Agruido = Ag;
[m,n] = size(Agruido);
for v = 1:1000
x = round(rand*m);
y = round(rand*n);
%Como MATLAB no indexa a partir de 0 protegemos el programa y
hacemos
%que empiece en 1
if x == 0
x = 1;
end
if y == 0
y = 1;
end
%Tambien se protege el programa
if x == 600
x = 598;
end
if y == 800
y = 798;
end
Agruido(x,y) = 255;
Agruido(x,y+1) = 255;
Agruido(x+1,y) = 255;
Agruido(x+1,y+1) = 255;
Agruido(x+2,y+1) = 255;
Agruido(x+2,y) = 255;
end
%se calculan 1000 puntos de ruido con valor 0 y se repite el proceso
%anterior
for v = 1:1000
x = round(rand*m);
y = round(rand*n);
%Como MATLAB no indexa a partir de 0 protegemos el programa y
hacemos
%que empiece en 1
if x == 0
x = 1;
end
if y == 0
y = 1;
end
%Tambien se protege el programa
if x == 600
x = 598;
end
if y == 800
y = 798;
end
Agruido(x,y) = 0;
Agruido(x,y+1) = 0;
Agruido(x+1,y) = 0;
Agruido(x+1,y+1) = 0;
Agruido(x+2,y+1) = 0;
Agruido(x+2,y) = 0;
end
Agruido = uint8(Agruido);
subplot(2,2,4)
imshow(Agruido)
title('Imagen con ruido')
h1=fspecial('average');
h2=fspecial('average',[9,9]);
media1=imfilter(fn,h1);
media2=imfilter(fn,h2);
subplot(2,2,1),subimage(Ag),title('Imagen original');
subplot(2,2,2),subimage(fn),title('Imagen con ruido');
subplot(2,2,3),subimage(media1),title('Filtrado mascara 3x3');
subplot(2,2,4),subimage(media2),title('Filtrado mascara 9x9');
%Una vez tenemos la imagen con ruido volvemos a ejecutar los filtros
%de suavizado con distintas imágenes, no cambia nada mas del código.
A.1.2 Segmentación
%Una vez que tenemos la imagen filtrada podemos dar como concluido el
%pre-procesamiento y pasamos ahora a la segmentacion
%En esta parte nos centraremos en la deteccion de los bordes de la
imagen
%Comenzamos por la detección de bordes binaria
imshow(A);
Ag = rgb2gray(A);
subplot(1,2,1)
imshow(Ag);
title('Imagen escala de grises')
for i = 1:m
for j = 1:1668
if I_gray(i,j) > 145
I_gray(i,j) = 255;
else
Ag(i,j) = 0;
end
end
end
subplot(1,2,1)
imshow(I_gray)
for i = 1:m
for j = 1:1465
if Ag(i,j) > 162
Ag(i,j) = 255;
else
Ag(i,j) = 0;
end
end
end
subplot(1,2,2)
imshow(Ag)
title('Imagen binaria')
GtN = uint8(GtN)
sf=fspecial('sobel');
sc=sf';
b1=imfilter(im1,sf);
b2=imfilter(im1,sc);
b3=imadd(b1,b2);
subplot(2,2,1),imshow(im1);
title('Imagen escala de grises')
%imshow(b2);
%imshow(b1);
imshow(b3);
title('Filtro de Sobel')
sf1 = fspecial('prewitt');
sc1 = sf1';
b11=imfilter(im1,sf1);
b21=imfilter(im1,sc1);
b31=imadd(b11,b21);
imshow(b31);
title('Filtro Prewitt')
gray_image = rgb2gray(image);
imshow(gray_image)
% Vemos que la mayoria de los circulos son mas oscuros que el fondo,
sin
% embargo, la funcion por defecto busca circulos mas claros que el
fondo,
% por lo que tenemos que añadir los parametros 'ObjectPolarity' and
'dark'
[centers,radii] = imfindcircles(image,[15
35],'ObjectPolarity','dark',...
'Sensitivity',0.9)
imshow(image)
h = viscircles(centers,radii);
%Hasta ahora hemos conseguido que reconozca todos los circulos excepto
los
%amarillos ya que estos eran mas claros que el fondo. Vamos a cambiar
los
%parametros de la funcion imfindcircles
[centersBright,radiiBright,metricBright] = imfindcircles(image,[15
35], ...
'ObjectPolarity','bright','Sensitivity',0.92,'EdgeThreshold',0.1);
delete(hBright)
hBright = viscircles(centersBright, radiiBright,'Color','b');
h = viscircles(centers,radii);
%La pasamos a tonos grises para ver si los circulos son mas claros o
%oscuros que el fondo
gray_image = rgb2gray(image);
imshow(gray_image)
[centers,radii] = imfindcircles(image,[15
35],'ObjectPolarity','dark',...
'Sensitivity',0.9)
imshow(image)
h = viscircles(centers,radii);
%Vemos que nos detecta todos los circulos, y nos da los centros de los
%circulos, lo que nos falta es saber en que cuadrante de la imagen
estan
m = size(image)
%Sabemos entonces que el ancho son 149 y el largo 150, lo que tiene
sentido
%porque pretende ser una imagen cuadrada.
n = length(radii);
numero_fichas = n
pos = [0,0,0;0,0,0;0,0,0];
color = [0,0,0;0,0,0;0,0,0];
for i = 1:n
if centro(i) < m(1)/3 & centro(i+n) < m(2)/3
pos(1,1) = 1;
if pos(1,1) == 1
color_pos1 = impixel(image,centro(i),centro(i+n));
if color_pos1(3) ~= 0
color(1,1) = 1;
else
color(1,1) = 2;
end
end
elseif centro(i) >= m(1)/3 & centro(i) < 2*m(2)/3 & centro (i+n) <
m(2)/3
pos(1,2) = 1;
if pos(1,2) == 1
color_pos2 = impixel(image,centro(i),centro(i+n));
if color_pos2(3) ~= 0
color(1,2) = 1;
else
color(1,2) = 2;
end
end
elseif centro(i) >= 2*m(1)/3 & centro(i+n) < m(2)/3
pos(1,3) = 1;
if pos(1,3) == 1
color_pos3 = impixel(image,centro(i),centro(i+n));
if color_pos3(3) ~= 0
color(1,3) =1;
else
color(1,3) = 2;
end
end
elseif centro(i) < m(1)/3 & centro(i+n) > m(2)/3 & centro(i+n) <
2*m(2)/3
pos(2,1) = 1;
if pos(2,1) == 1
color_pos4 = impixel(image,centro(i),centro(i+n));
if color_pos4(3) ~= 0
color(2,1) = 1;
else
color(2,1) = 2;
end
end
elseif centro(i) >= m(1)/3 & centro(i) < 2*m(2)/3 & centro(i+n) >
m(2)/3 & centro(i+n) < 2*m(2)/3
pos(2,2) = 1;
if pos(2,2) == 1
color_pos5 = impixel(image,centro(i),centro(i+n));
if color_pos5(3) ~= 0
color(2,2) = 1;
else
color(2,2) = 2;
end
end
elseif centro(i) >= 2*m(1)/3 & centro(i+n) > m(2)/3 & centro(i+n)
< 2*m(2)/3
pos(2,3) = 1;
if pos(2,3) == 1
color_pos6 = impixel(image,centro(i),centro(i+n));
if color_pos6(3) ~= 0
color(2,3) = 1;
else
color(2,3) = 2;
end
end
elseif centro(i) < m(1)/3 & centro(i+n) >= 2*m(2)/3
pos(3,1) = 1;
if pos(3,1) == 1
color_pos7 = impixel(image,centro(i),centro(i+n));
if color_pos7(3) ~= 0
color(3,1) = 1;
else
color(3,1) = 2;
end
end
elseif centro(i) >= m(1)/3 & centro(i) < 2*m(2)/3 & centro(i+n) >=
2*m(2)/3
pos(3,2) = 1;
if pos(3,2) == 1
color_pos8 = impixel(image,centro(i),centro(i+n));
if color_pos8(3) ~= 0
color(3,2) = 1;
else
color(3,2) = 2;
end
end
elseif centro(i) >= 2*m(1)/3 & centro(i+n) >= 2*m(2)/3
pos(3,3) = 1;
if pos(3,3) == 1
color_pos9 = impixel(image,centro(i),centro(i+n));
if color_pos9(3) ~= 0
color(3,3) = 1;
else
color(3,3) = 2;
end
end
end
end
tablero = color
clc
clear all
close all
image = imread('objetos_negro2.jpeg');
imshow(image)
image = rgb2gray(image);
imshow(image)
image = wiener2(image,[50,50]);
figure
imshow(image)
image = im2bw(image,0.45);
figure
imshow(image)
image = bwareaopen(image,130);
figure
imshow(image)
se = strel('disk',5);
image = imclose(image,se);
figure
imshow(image)
%Con esto hemos conseguido tener los espacios bien delimitados, ahora
vamos
%a utilizar los bordes de los objetos para delimitar las regiones y
%caracterizar cada objeto
[B,L] = bwboundaries(image,'noholes');
imshow(label2rgb(L,@jet,[.5 .5 .5]))
hold on
for k = 1: length(B)
boundary = B{k}; %bucle para dibujar los contornos de las regiones
plot(boundary(:,2),boundary(:,1),'w','LineWidth',2)
end
%Ahora vamos a empezar a obtener los parametros que nos van a permitir
%identificar los objetos
%Extraemos la informacion del centro del objeto y del area del mismo
stats = regionprops(L,'Area','Centroid');
threshold = 0.94;
for k = 1:length(B)
boundary = B{k};
delta_sq = diff(boundary).^2;
perimeter = sum(sqrt(sum(delta_sq,2))); %Calculamos el perimetro
area = stats(k).Area; %Calculamos el area
metric = 4*pi*area/perimeter^2; %Calculamos una metrica
metric_string = sprintf('%2.2f',metric); %Asignamos cada metrica a
cada region
if metric > threshold
centroid = stats(k).Centroid;
plot(centroid(1),centroid(2),'ko')
end
text(boundary(1,2)-
35,boundary(1,1)+13,metric_string,'Color','k','FontSize',15,'FontWeigh
t','bold')
end