Visión Artificial
Prueba de evaluación continua 1
2019-2020
Alumno: Alberto Martínez Montenegro
DNI:
Centro Asociado: Pontevedra-Vigo
Teléfono de contacto:
Email:
Página 2 de 58
Índice
Ejercicio 1 .................................................................................................. 3
Ejercicio 2 ................................................................................................ 13
Ejercicio 3 ................................................................................................ 23
Ejercicio 4 ................................................................................................ 33
Ejercicio 5 ................................................................................................ 38
Visión Artificial Alberto Martínez Montenegro
Página 3 de 58
1) Eliminación de ruido en imágenes escaneadas.
En primer lugar, se enumeran a continuación los diferentes tipos de ruido
encontrados en las imágenes:
- Ruido “Sal y pimienta”: Los píxeles negros aislados, distribuidos de forma
aleatoria, que están presentes en todas las imágenes. Se eliminan fácilmente
aplicando un filtro de mediana a la imagen total.
-
-
- Líneas ruidosas con patrón fijo: En las imágenes N_307_GLS_TOTAL-ev5-
h.png, N_321_MGB_TOTAL-ev3-h.png y N_326_PLM_TOTAL-ev5-r.png hay
unas líneas de ruido que siguen cierto patrón. Son fáciles de eliminar con el
mismo método que el ruido descrito en el punto anterior ya que están
compuestas por píxeles aislados cuya intensidad difiere de sus vecinos,
aunque la aplicación creada también dispone de otros operadores que son
adecuados para eliminarlas.
Visión Artificial Alberto Martínez Montenegro
Página 4 de 58
- Líneas ruidosas con color característico: En las imágenes N_318_HDM_TOTAL-
ev3-mm.png, N_325_RCC_TOTAL-ev1-c.png, N_325_RCC_TOTAL-ev1-mm.png y
N_331_JVC_TOTAL-ev1-h.png se observan unas líneas de ruido que se
caracterizan por tener una tonalidad de gris diferente al resto de la imagen, esto
supone una ventaja a la hora eliminar este ruido, ya que se ha creado un operador
que permite eliminar cualquier color concreto de la imagen.
- Manchas a causa del escaneado de la imagen: En las imágenes
N_308_CLQ_TOTAL-ev2-h.png, N_320_MªTWG_TOTAL-ev1-circulo.png,
N_328_THS_TOTAL-ev1-h.png, N_338_MET_TOTAL-ev2-t.png se observan unas
manchas típicas de los documentos escaneados. Son difíciles de eliminar ya que
algunas ocultan parcialmente parte del dibujo que ha de mostrarse en la imagen.
Visión Artificial Alberto Martínez Montenegro
Página 5 de 58
Para la eliminación de los diferentes tipos de ruido descritos, se han programado en
Python diferentes operadores. La aplicación diseñada permite al usuario ir aplicando
los diferentes operadores según se crea conveniente mediante la siguiente GUI:
A continuación, se explica la función de cada uno de los operadores con una serie
de parejas de imágenes que ejemplifican su uso.
• Aplicar filtro de mediana: Se aplica el filtro de mediana que se describe en
los apuntes de la asignatura. La aplicación da a escoger entre 3 valores
para N (3, 5 o 7).
Visión Artificial Alberto Martínez Montenegro
Página 6 de 58
• Aplicar filtro RGB: La aplicación solicita al usuario que le pase como
parámetro un color RGB, que será eliminado de la imagen, es decir, los
píxeles de ese color serán cambiados por pixeles de color blanco. En el
siguiente ejemplo se muestra el uso de este operador eliminando el color
RGB(169,169,169), que está presente en varias de las imágenes objetivo
de esta práctica.
Visión Artificial Alberto Martínez Montenegro
Página 7 de 58
• Aplicar filtro Blanco/Negro: La aplicación solicita al usuario que seleccione
una región de interés (ROI). Cualquier tonalidad de gris será eliminada de la
región seleccionada, dejando únicamente los colores RGB negro (0, 0, 0) y
blanco (255, 255, 255). Es útil para empezar a eliminar las manchas
grandes que se comentaron al describir los diferentes tipos de ruido
encontrados.
• Erosionar y Dilatar: Estos operadores tienen funcionalidades opuestas.
Mediante la erosión obtendremos un efecto de adelgazamiento en la ROI
en la que estemos trabajando, mientras que con la dilatación obtendremos
un efecto de expansión. En la siguiente imagen se ha aplicado erosión en la
parte izquierda y dilatación en la derecha:
Visión Artificial Alberto Martínez Montenegro
Página 8 de 58
• Guardar y recomponer esqueleto: Este operador permite guardar el
esqueleto de la imagen en un determinado momento, y después usar este
esqueleto para recomponer el contorno de la imagen si es que éste ha sido
borrado al ir aplicando otros operadores:
Visión Artificial Alberto Martínez Montenegro
Página 9 de 58
Por último, se analizarán las dos imágenes que se piden en el enunciado.
Se muestra a continuación la secuencia de operadores aplicados para eliminar
el ruido en la imagen “N_328_THS_TOTAL-ev1-h.png”:
1- Se aplica el filtro Blanco/Negro en la parte inferior de la imagen:
Visión Artificial Alberto Martínez Montenegro
Página 10 de 58
2- Se aplica el filtro de mediana con N=3 a toda la imagen:
3- Se aplica erosión al borde inferior de la imagen:
Visión Artificial Alberto Martínez Montenegro
Página 11 de 58
Se muestra a continuación la secuencia de operadores aplicados para eliminar
el ruido en la imagen “N_307_GLS_TOTAL-ev5-h.png”:
1- Aplicamos el filtro Blanco/Negro a la parte izquierda de la imagen:
Visión Artificial Alberto Martínez Montenegro
Página 12 de 58
2- Dilatamos la casa de la izquierda, ya que con unos bordes tan finos no
resistiría la aplicación del filtro de mediana:
3- Aplicamos 3 iteraciones de filtro de mediana con N=3:
Visión Artificial Alberto Martínez Montenegro
Página 13 de 58
2. Transformaciones geométricas.
A) Reescalar la imagen para obtener una imagen de 200x200 pixels
Simplemente se aplica el operador cv2.resize() con las proporciones deseadas:
Visión Artificial Alberto Martínez Montenegro
Página 14 de 58
B) Inclinar 30 grados a la derecha (se mantienen las coordenadas y), girar 90 grados a la
izquierda (centro de giro en el centro de la imagen) y reescalar a la mitad en ambos ejes
(toda la transformación con una única matriz obtenida por composición de matrices). ¿El
orden de las transformaciones es importante?
Para cada una de las transformaciones, se ha calculado una matriz de transformación siguiendo
las pautas que se indican en las figuras del enunciado.
Para la primera transformación (inclinar 30 grados a la derecha), se ha usado la matriz:
Siendo Phi igual a 30 grados.
Para la segunda transformación (girar 90 grados a la izquierda con eje de giro en el centro de la
imagen), se han multiplicado las siguientes matrices:
Con lo cual, tenemos la siguiente matriz:
Visión Artificial Alberto Martínez Montenegro
Página 15 de 58
Siendo:
X= desplazamiento horizontal necesario para que el punto central de la imagen girada coincida
con el punto central original.
Y = desplazamiento vertical necesario para que el punto central de la imagen girada coincida
con el punto central original.
Theta = 270 grados.
Para la tercera transformación (reescalar a la mitad en ambos ejes), se ha usado la matriz:
Siendo:
W= 1/2
H= 1/2
Con lo cual la matriz de transformación final será el siguiente producto de matrices:
Respondiendo a la pregunta del enunciado, el orden de las transformaciones SÍ es importante.
Esto puede comprobarse de dos maneras:
- Haciendo manualmente las operaciones puede observarse que el resultando será
diferente si el orden varía.
- Debido a que el producto de matrices no es conmutativo, si las multiplicaciones se
hacen en diferente orden se obtendrá una matriz de transformación final diferente.
Visión Artificial Alberto Martínez Montenegro
Página 16 de 58
La imagen resultante de aplicar esta matriz de transformación es la siguiente:
Como puede observarse, hay una porción de imagen que no es visible, esto se debe a que en la
operación “girar 90 grados a la izquierda (centro de giro en el centro de la imagen)”, parte
de la imagen pasa a estar en la parte negativa del eje de coordenadas, con lo cual no será visible
ni siquiera después de reescalar a la mitad en ambos ejes.
Se ha considerado que lo correcto es escoger como “centro de la imagen” el centro del romboide
resultante de efectuar la primera operación.
Visión Artificial Alberto Martínez Montenegro
Página 17 de 58
C) Utilizar la función cv2.warpPolar para obtener una imagen logPolar cuadrada,
centrada en el centro de la imagen original con una fila por grado y ajustada para ver toda
la imagen original. Comentar el resultado obtenido.
Se ha utilizado la función warpPolar con los siguientes parámetros:
- dsize: (360,360)
Dado que se nos pide que la imagen sea cuadrada, y tenga una fila por grado, estas son
las únicas dimensionas posibles.
- center: (ancho/2, alto/2)
El punto medio de la imagen será el centro del bounding circle.
𝒂𝒏𝒄𝒉𝒐 𝟐 𝒂𝒍𝒕𝒐 𝟐
- maxRadius: √( ) +( )
𝟐 𝟐
Dado que se nos pide que se abarque toda la imagen, el radio debe ser la distancia entre
el centro de la imagen y una esquina. Se calcula mediante el teorema de Pitágoras.
- flags: cv2.WARP_POLAR_LOG.
Dado que se nos pide que sea una imagen logPolar, debe utilizarse el flag
cv2.WARP_POLAR_LOG
Combinando estos datos, se escribe la siguiente función en Python:
La imagen resultante es la siguiente:
Visión Artificial Alberto Martínez Montenegro
Página 18 de 58
La imagen ha sido remapeada a coordenadas polares, esto quiere decir que los pixeles han sido
reordenados a partir del “barrido” hecho por el radio de circunferencia que define el bounding
circle.
Lo hecho en este apartado es exactamente lo mismo que se hace en el ejemplo del documento de
ayuda que se enlaza en el enunciado:
La única diferencia es que en nuestro caso se nos pide una salida con unas dimensiones
Visión Artificial Alberto Martínez Montenegro
Página 19 de 58
específicas y un radio que abarque la totalidad de la imagen.
D) Recuperar la imagen original a partir de la obtenida en el aparado c). Comentar el
resultado obtenido.
Para recuperar la imagen, simplemente se definen las dimensiones originales en el parámetro
dsize, y se usa el flag cv2.WARP_INVERSE_MAP, este es el resultado que se obtiene:
Como puede observarse, la calidad empeora a medida que nos alejamos del centro, esto se debe
a que hemos redimensionado la imagen a 360x360, con lo cual se ha perdido información.
Además, esa perdida de información se acentúa en las regiones de la imagen más alejadas del
centro, ya que al pasar la imagen a coordenadas polares, esas zonas se “comprimen” a un
espacio más pequeño, mientras que con la zona central ocurre lo contrario.
Visión Artificial Alberto Martínez Montenegro
Página 20 de 58
Si repetimos el apartado C del enunciado sin redimensionar la imagen a 360x360, y después la
recuperamos, puede observarse que la calidad mejora enormemente:
Visión Artificial Alberto Martínez Montenegro
Página 21 de 58
E) deformar la imagen original de manera que la mitad horizontal izquierda de la imagen
quede comprimida en un tercio de la imagen final y la parte derecha se expanda para
ocupar los dos tercios restantes. ¿Qué operador considera que se debe utilizar para
realizar esta operación warpAffine o warpPerspective? Justifique la respuesta.
La imagen que se nos pide requiere que se trate de forma diferente dos regiones de la imagen,
así que tanto si usamos warpAffine como warpPerspective, debemos realizar una
transformación para la parte izquierda y otra para la derecha.
Se puede usar warpPerspective para visualizar la mitad izquierda desde una determinada
perspectiva y la mitad derecha desde otra distinta. Combinando estas dos perspectivas de la
forma adecuada se puede lograr crear la imagen que se nos pide en el enunciado.
También se podría definir un mapeado de pixeles para conseguir la solución con la función
remap() de openCV, lo cual permitiría realizar el proceso en una sola operación.
Sin embargo, se ha considerado más correcto e intuitivo resolver este apartado con warpAffine y
las siguientes matrices de transformación:
Para la mitad izquierda:
Siendo W = 2/3.
Para la mitad derecha:
Siendo W= 4/3
En la función de Python, definimos esas matrices mediante puntos originales y puntos destino
para aplicar la función warpAffine:
Visión Artificial Alberto Martínez Montenegro
Página 22 de 58
Combinando las dos mitades transformadas con dichas matrices, obtenemos el siguiente
resultado:
Visión Artificial Alberto Martínez Montenegro
Página 23 de 58
3. Calibración de cámara.
3.1) Realice con spyder los tutoriales de openCV dedicados a la calibración de la cámara y
estimación de la pose. Las imágenes para la calibración se encuentran en el directorio
“PEC1/data/calib”.
Deberá entregar el código con los resultados de la calidad de la calibración y con la
implementación que dibuja un cubo indicando la orientación del tablero cambiando el
color de la base de verde a roja y las aristas superiores en color amarillo.
El código de la aplicación Python creada para este apartado, se encuentra en el fichero
“Ejercicio3.py” que se ha entregado. El programa está creado a partir de los fragmentos de
código que se pueden encontrar en los tutoriales enlazados, aunque se han editado varias partes
para cumplir los requisitos pedidos en el enunciado.
Al ejecutar el programa, se irán mostrando todos los patrones de tablero encontrados en las
imágenes:
Visión Artificial Alberto Martínez Montenegro
Página 24 de 58
Durante la ejecución, puede comprobarse que la función cv2.findChessboardCorners() no
encuentra el patrón de tablero buscado en las imágenes “left09.jpg” y “left11.jpg”, por lo que no
serán tenidas en cuenta para la calibración.
También se irán mostrando los cubos de definen la estimación de pose, se ha editado el código
de tal forma que se muestren los colores pedidos en el enunciado:
El objetivo del programa es calcular la distorsión radial de la cámara, está distorsión podrá
medirse a partir del índice de calidad de calibración, la matriz de cámara, los coeficientes de
distorsión y los vectores de rotación y de traslación.
A continuación, se muestra la salida que produce el programa creado a la hora de calibrar las
imágenes que se nos pide:
Calidad de calibración: 0.15536906910078815
Matriz de cámara:
[[534.07088364 0. 341.53407553]
[ 0. 534.11914595 232.9456526 ]
[ 0. 0. 1. ]]
Visión Artificial Alberto Martínez Montenegro
Página 25 de 58
Coeficientes de distorsión:
[[-2.92971637e-01 1.07706962e-01 1.31038377e-03 -3.11018811e-05
4.34798104e-02]]
Vectores de rotación:
[array([[-0.43239599],
[ 0.25603401],
[-3.08832021]]), array([[ 0.41531697],
[ 0.65664497],
[-1.3373494 ]]), array([[-0.2645143 ],
[-0.39360849],
[-2.74787379]]), array([[-0.37843358],
[-0.18064237],
[-3.11615996]]), array([[-0.45993978],
[-0.3142018 ],
[-1.76122223]]), array([[-0.29979221],
[ 0.39216377],
[-1.4348239 ]]), array([[-0.32034625],
[ 0.1597993 ],
[-1.24149595]]), array([[-0.45883216],
[-0.08848877],
[-1.33510786]]), array([[-0.35367631],
[-0.24363035],
[-1.56874295]]), array([[ 0.30697385],
[ 0.5038552 ],
[-1.82824733]]), array([[-0.17288944],
[-0.46764681],
[ 1.34745198]])]
Vectores de traslación:
[array([[ 3.79739146],
[ 0.89895018],
[14.8593055 ]]), array([[-2.12419184],
[ 1.84550818],
[12.81229187]]), array([[3.03685642],
[2.74656588],
[9.90005138]]), array([[ 2.82321756],
[ 2.22374307],
[10.95762951]]), array([[-1.13991523],
[ 2.67424464],
[ 9.56289277]]), array([[ 1.60364763],
Visión Artificial Alberto Martínez Montenegro
Página 26 de 58
[ 3.81296375],
[16.12054474]]), array([[-5.94286695],
[ 2.39629427],
[16.77859026]]), array([[-3.27916485],
[ 2.15811689],
[11.72833343]]), array([[-2.89985494],
[ 2.62066993],
[10.57699258]]), array([[-1.22339632],
[ 3.52139948],
[15.67311789]]), array([[ 1.81888151],
[-4.2642919 ],
[12.45728517]])]
Como puede observarse, los valores parecen se correctos, ya que tenemos un coeficiente de
calidad de calibración cercano a 0 y la matriz de cámara tiene unos valores correctos y cercanos
al punto medio de imagen.
Visión Artificial Alberto Martínez Montenegro
Página 27 de 58
3.2) Suponga que puede localizar puntos significativos de la cabeza de una persona (esto se
hará más adelante en el curso). ¿Se le ocurre alguna manera de estimar hacia dónde mira
la cabeza? Describa cómo lo haría.
Podríamos escribir un programa que detectase en qué dirección mira una persona a partir de una
imagen usando el mismo método de estimación de pose que se explica en los tutoriales.
La única diferencia sería que en lugar de usar la función cv2.findChessboardCorners()
tendríamos que usar una función que detectase los puntos significativos de la cabeza de una
persona (tal y como se presupone en el enunciado). A partir de esos puntos significativos
detectados por la función, tendría que poder deducirse un cubo que nos indique la orientación de
la cabeza, tal y como el cubo de los tutoriales nos indica la orientación del tablero de ajedrez.
La siguiente imagen ejemplifica lo descrito en el párrafo anterior:
Supongamos que hemos creado la función cv2.findFacePoints() que detecta los puntos blancos
de la imagen, y nos permite a través de ellos deducir el plano del cubo más cercano a la cara.
Con esto ya podemos estimar la dirección en la que mira la cabeza.
Visión Artificial Alberto Martínez Montenegro
Página 28 de 58
3.3) Haga la calibración de su propia cámara web (si la tiene, si no, tome fotos con una
cámara fotográfica y calíbrela). Describa cómo lo realizó.
Para este apartado se ha hecho la calibración de la cámara web “Logitech Quickcam for
Notebooks”, una cámara web con una resolución máxima de 640x480 pixeles.
El procedimiento seguido para la calibración ha sido exactamente el mismo que para el apartado
3.1 de este ejercicio, simplemente se han sustituido las imágenes de calibración facilitadas por
equipo docente, por otras tomadas con la cámara Logitech.
Para la realización de las fotografías, he imprimido el siguiente patrón de tablero en un folio
DINA4:
He pegado el folio a un tablero de ajedrez para evitar que se doblase, y tomado las siguientes
fotografías:
Visión Artificial Alberto Martínez Montenegro
Página 29 de 58
El programa creado detectó correctamente los patrones y también estimo la pose:
La salida con los datos de la calibración fue la siguiente:
Calidad de calibración: 0.4260454138311156
Matriz de cámara:
[[785.01985659 0. 325.57752429]
[ 0. 788.19696026 242.11229766]
[ 0. 0. 1. ]]
Coeficientes de distorsión:
[[ 1.40814821e-01 -2.75833739e+00 5.51558775e-03 -9.19204759e-03
9.22783602e+00]]
Vectores de rotación:
[array([[ 0.04155427],
[-0.64659742],
[-0.08474401]]), array([[ 0.2692878 ],
[ 0.13381683],
[-3.08391864]]), array([[-0.70837789],
[-0.04479579],
[ 3.02762344]]), array([[-0.6939613 ],
[-0.03820177],
[ 3.02887103]]), array([[ 0.07798034],
[-0.42163105],
[-0.01388276]]), array([[-0.09928032],
[-0.53980975],
[-0.17452034]]), array([[-0.09179741],
Visión Artificial Alberto Martínez Montenegro
Página 30 de 58
[ 0.50625336],
[ 0.20518909]]), array([[-0.07916692],
[ 0.53640356],
[ 0.21238103]]), array([[-0.50629282],
[-0.04600797],
[-0.0079325 ]])]
Vectores de traslación:
[array([[-7.72118834],
[-1.89799787],
[22.68210415]]), array([[ 1.55551693],
[ 2.48498291],
[21.57661244]]), array([[-1.56567930e-03],
[ 2.75937376e+00],
[ 2.52088559e+01]]), array([[-0.04791822],
[ 2.79463884],
[25.18568681]]), array([[-5.51349636],
[-2.17236326],
[18.81301316]]), array([[-6.62183278],
[-1.72029448],
[20.55508495]]), array([[-0.91387178],
[-2.88001109],
[25.80378535]]), array([[-1.20235108],
[-2.84224325],
[25.40508098]]), array([[-0.96354265],
[-2.11196381],
[32.2694124 ]])]
El programa, antes de finalizar su ejecución, también guarda una imagen llamada
“calibresult.png” que aplica la corrección de distorsión correspondiente a una de las imágenes.
A continuación, se muestra la imagen resultado de aplicar la corrección, se pude apreciar en las
esquinas de la imagen cómo el algoritmo corrige la distorsión:
Visión Artificial Alberto Martínez Montenegro
Página 31 de 58
Visión Artificial Alberto Martínez Montenegro
Página 32 de 58
3.4) Si tiene una cámara a la que se le pueden acoplar dos objetivos, uno de 25mm de
distancia focal y otro de 50mm, ¿cual eligiría para obtener imágenes con mayor ángulo de
visión? Justifique la respuesta.
Elegiría el objetivo de 25mm, ya que cuanto menor sea la distancia focal, mayo será el ángulo
de visión.
La distancia focal es la distancia en que existe entre el plano focal del sensor y el centro óptico
de la lente. En la siguiente imagen, podemos ver a la derecha de la lente el plano focal del
sensor verde, y a una distancia mayor, el plano focal del sensor rojo:
El objeto Q produce la imagen Q', cuyo tamaño es abarcable por parte del sensor verde, que
tiene una distancia focal menor que el sensor rojo.
Sin embargo, si obtuviésemos la imagen Q’ a la altura del sensor rojo, podríamos comprobar
fácilmente que dicho sensor no sería capaz de abarcarla, ya que el mayor ángulo que abarca es
el correspondiente al objeto P.
Visión Artificial Alberto Martínez Montenegro
Página 33 de 58
4. Flujo Óptico.
4.1) Comente la diferencia entre los enfoques utilizados por los dos programas:
lukas_kanade_track.py y optical_flow1.py
El programa “lukas_kanade_track.py” usa el método Lucas-Kanade, mientras que
“optical_flow1” usa el enfoque de flujo óptico denso, basado en el algoritmo de Gunner
Farneback.
Tal y como se explica en el en tutorial, el método Lucas-Kanade elige una serie de puntos de
interés en el primer fotograma. La forma de decidir estos puntos de interés puede variar
dependiendo de la implementación que usemos, en el tutorial se explica que en openCV usamos
la función “cv2.goodFeaturesToTrack()” para localizarlos.
El algoritmo va obteniendo el flujo óptico de estos puntos de interés valiéndose en cada paso de:
• El fotograma previo.
• Los puntos previos.
• El nuevo fotograma.
Devuelve los nuevos puntos de interés, en caso de que hayan sido encontrados.
A diferencia del método Lucas-Kanade, el método de flujo óptico denso computa el flujo óptico
de todos los píxeles del fotograma. Con este método se obtiene una matriz de dos canales con
los vectores de flujo óptico, se encuentra su magnitud y dirección y se colorea el resultado para
una mejor visualización.
Además de la diferencia descrita en el párrafo anterior, observando el funcionamiento de cada
método puede deducirse que el método de flujo óptico denso es mucho más lento y requiere
mayor capacidad computacional que el método Lucas-Kanade, pero puede ser más preciso.
Visión Artificial Alberto Martínez Montenegro
Página 34 de 58
4.2) ¿Por qué el primero no detecta el movimiento en las regiones suavizadas de la
imagen?
Tal y como se ha explicado en el apartado anterior, el algoritmo Lucas-Kanade elige una serie
de puntos de interés en los primeros fotogramas para ir rastreando su flujo óptico a lo largo de la
secuencia de fotogramas. Esta selección de puntos de interés se basa en el método de detección
de esquinas “Shi-Tomasi”.
Únicamente será rastreado el flujo óptico de los puntos que el algoritmo Shi-Tomasi catalogue
como esquinas. Para ser catalogado como esquina, un punto ha de cumplir los requisitos que se
pasan como parámetro en el programa:
El parámetro más importante en nuestro caso es el nivel de calidad, ya que si el nivel de calidad
de la esquina no supera 0.3, será descartada y no se rastreará su flujo óptico.
En la siguiente captura podemos ver cuáles son los puntos detectados como esquinas por
nuestro programa:
Ese es el motivo por el cual el primer programa no detecta el movimiento de las zonas
suavizadas, porque no tienen puntos que sean catalogados como esquinas y por lo tanto su flujo
óptico no es rastreado.
Visión Artificial Alberto Martínez Montenegro
Página 35 de 58
4.3) ¿Qué hace la función draw_hsv() en optical_flow1.py?
Existen varias maneras de visualizar la forma en la que el algoritmo Gunner Farneback rastrea
el flujo óptico de la totalidad de la imagen, las más usadas son las siguientes:
-Mediante una malla de puntos sobre la imagen original, dibujando líneas dónde se detecte
movimiento:
-Mediante un fondo negro, y resaltando las zonas en las que se detecta movimiento con colores
en formato HSV:
-Mediante deformación, se va deformando la imagen original a partir del flujo óptico detectado:
Visión Artificial Alberto Martínez Montenegro
Página 36 de 58
En nuestro programa, por defecto sólo se ejececutará la visualización mediante malla,
pero si cambiamos la línea 72 de “show_hsv = False” a “show_hsv = True”, se ejecutará
la llamada a la función draw_hsv() por la que se pregunta en este apartado.
El objetivo de esta función no es otro que mostrar la visualización de rastreo de flujo
óptico mediante colores HSV (Hue Saturation Value) en lugar de usar el método de
malla mencionado anteriormente. Si hacemos ese cambio en la línea 72 se ejecutará la
visualización simultánea de los dos métodos y podremos apreciar las diferencias, tal y
como se muestra en la siguiente captura:
Visión Artificial Alberto Martínez Montenegro
Página 37 de 58
4.4) ¿Qué información contienen las variables “flow” y “res” en la función warp_flow() de
optical_flow1.py?
La función warp_flow se usa para obtener la visualización a través de deformación que se
describió en el apartado anterior.
Para activar esta visualización hay que cambiar la línea 73 de “show_glitch = False” a
“show_glitch = True” para que se ejecute la llamada a warp_flow().
La variable “flow” contiene la matriz de flujo óptico detectado, mientras que img contiene el
fotograma original. Después de ejecutar las operaciones necesarias, la función warp_flow()
llama a la función remap de openCV para componer la imagen por deformación y almacenarla
en la variable “res”.
Por lo tanto, tenemos:
• Variable “flow”: Contiene la matriz con el flujo óptico detectado en un determinado
momento.
• Variable “res”: Contiene la imagen resultado de ejecutar una serie de operaciones de
combinación entre la imagen original (“img”) y la variable “flow”
En la siguiente captura se puede ver un ejemplo de la visualización de la variable res de la
función warp_flow():
Visión Artificial Alberto Martínez Montenegro
Página 38 de 58
5. Segmentación sin conocimiento del dominio.
5.1) Explique la diferencia entre umbralización global (global thresholding) y local
(adaptive thresholding). Indique las ventajas e inconvenientes de cada una de ellas.
Utilice openCV para ejemplificarlo sobre las siguientes imágenes del directorio
PEC1/data/threshold/
Tal y cómo se explica en la documentación de OpenCV, la umbralización global es una técnica
de procesado de imágenes en la que se obtiene una imagen resultado a partir de una imagen
origen, siguiendo el siguiente procedimiento:
1. Se establece un valor umbral, será el mismo para toda la imagen.
2. Se examina cada pixel, si el valor del pixel está por debajo del valor umbral, el pixel se
establece a 0, si no, se establece al valor máximo.
Por lo tanto, el uso de este método nos hará obtener unas imágenes resultado en blanco y negro,
sin ninguna tonalidad de gris. A continuación, se muestran las imágenes de la carpeta
PEC1/data/threshold/ procesadas con el algoritmo de umbralización global que puede
encontrarse en la documentación de OpenCV:
Visión Artificial Alberto Martínez Montenegro
Página 39 de 58
Visión Artificial Alberto Martínez Montenegro
Página 40 de 58
Como puede observarse, los resultandos son aceptables en “TH_noisy2” y “TH_notes”, pero no
se obtienen unos buenos resultados en las otras imágenes. Esto sucede porque en las demás
imágenes hay distintos niveles de iluminación en algunas zonas, lo cual provoca que un píxel
que debería estar por debajo del umbral, con esa iluminación esté por encima y viceversa.
En la umbralización local, a diferencia de en la global, se determina el valor umbral de cada
píxel examinando una pequeña zona que lo rodea, con lo cual, el umbral irá variando
dependiendo del píxel que se esté analizando en cada momento. Con esta técnica obtendremos
mejores resultados en las imágenes que tienen diferente iluminación en algunas de sus zonas.
OpenCV nos ofrece dos métodos para aplicar la umbralización global:
• cv.ADAPTIVE_THRESH_MEAN_C: El valor umbral es la media de los píxeles
vecinos menos una constante C.
• cv.ADAPTIVE_THRESH_GAUSSIAN_C: El valor umbral es la suma de peso
gaussiano de los píxeles vecinos menos una constante C.
A continuación, se muestran las imágenes obtenidas con ambos métodos:
Visión Artificial Alberto Martínez Montenegro
Página 41 de 58
Visión Artificial Alberto Martínez Montenegro
Página 42 de 58
Como puede observarse, en imágenes como “TH_TE”, “TH_scanTable” o “TH_scanText” los
resultados son mucho mejores usando la umbralización local, mientras que en otros casos, en
especial cuando no hay efectos de iluminación, es más adecuada la umbralización global, como
en “TH_notes”.
Visión Artificial Alberto Martínez Montenegro
Página 43 de 58
5.2) Clustering k-means. Describa brevemente, con sus palabras, la idea detrás de este
algoritmo de segmentación y dibuje un diagrama de flujo de su funcionamiento. Aplíquelo
a la segmentación de la figura 6, de manera que se distinga la sustancia blanca (región más
clara del cerebro) y la sustancia gris (región nenos clara, grisácea). Otras estructuras que
hay en la cabeza son el cráneo (hueso, hiperintenso) y el líquido cerebroespinal, que no se
ve (pixeles negros) en esta modalidad de imagen de resonancia magnética, por lo que no se
distingue del fondo. No espere una segmentación perfecta, pero sí aproximada. Pruebe con
distinto número de clases y justifique la configuración que obtiene visualmente el mejor
resultado.
El algoritmo k-means consiste en agrupar los elementos de un conjunto en k grupos, basándose
en sus características. Es el usuario del algoritmo el que escoge el número de k de grupos que se
formarán, por lo tanto, k es un parámetro que ha de conocerse cuando comience la ejecución del
algoritmo. Para medir la distancia, suele usarse la distancia euclídea.
Una vez escogido k el algoritmo seguirá estos cuatro pasos:
1- Se establecen k centroides en el espacio de los datos, por ejemplo, escogiéndolos
aleatoriamente.
2- Cada elemento de los datos es asignado al grupo de su centroide más cercano.
3- Se actualiza la posición de los centroides tomando como nuevo centroide la posición del
promedio de los elementos pertenecientes a su grupo.
4- Se repiten los pasos 2 y 3 hasta que los centroides no se mueven, o se mueven por
debajo de una distancia umbral en cada paso.
Según estos pasos, tendríamos el siguiente diagrama de flujo:
Visión Artificial Alberto Martínez Montenegro
Página 44 de 58
Para visualizar el funcionamiento del algoritmo, se usará la web
https://www.naftaliharris.com/blog/visualizing-k-means-clustering/, que permite
visualizar paso a paso la ejecución del algoritmo k-medias.
Se ejecutará un ejemplo sencillo con k=3.
-Paso 1: Se escogen aleatoriamente los centroides: rojo, azul y verde:
Visión Artificial Alberto Martínez Montenegro
Página 45 de 58
Paso 2: Cada elemento de los datos es asignado al grupo de su centroide más cercano:
Paso 3: Se actualiza la posición de los centroides tomando como nuevo centroide la posición del
promedio de los elementos pertenecientes a su grupo:
Visión Artificial Alberto Martínez Montenegro
Página 46 de 58
Paso 4: Se repiten los pasos 2 y 3 hasta que los centroides no se mueven, o se mueven por
debajo de una distancia umbral en cada paso:
Después de varias iteraciones, los centroides a penas se desplazan:
Visión Artificial Alberto Martínez Montenegro
Página 47 de 58
El algoritmo k-medias orientado a segmentación de imágenes, funciona exactamente de la
forma descrita, sólo que en lugar de usar la distancia euclídea para medir la similitud entre
dos puntos (píxeles), se compara el color o los niveles de intensidad del píxel.
Visión Artificial Alberto Martínez Montenegro
Página 48 de 58
A continuación, se muestran los resultados de aplicar el algoritmo a la imagen pedida,
“brain1.png”, con K=2, K=3, K=4, K=5 y K=6:
K=2:
K=3:
K=4:
Visión Artificial Alberto Martínez Montenegro
Página 49 de 58
K=5:
K=6:
En mi opinión, los resultados con K=4 son los que mejor se adecúan a lo pedido en el
enunciado, es decir, una distinción entre la sustancia blanca y la sustancia gris del
cerebro.
Visión Artificial Alberto Martínez Montenegro
Página 50 de 58
5.3) Algoritmos de watershed y meanshift.
a) Describa brevemente, con sus palabras, la idea detrás de estos dos algoritmos de
segmentación y dibuje un diagrama de flujo de su funcionamiento.
La idea detrás del algoritmo watershed es la siguiente:
1. Nos imaginamos la imagen a analizar como una superficie en relieve donde los
píxeles con intensidades más altas son picos elevados y los píxeles con intensidades más
bajas son valles profundos.
2. Comenzamos el algoritmo detectando los mínimos locales de intensidades, estos
mínimos locales serán los valles profundos que se citaron en el párrafo anterior. Una vez
detectados se van llenando de agua, cada valle se llena con agua de diferente color con
el objetivo de etiquetarlo.
3. A medida que el agua sube, dependiendo de los picos cercanos, el agua de diferentes
valles comenzará a fusionarse. Para evitar este hecho, se construyen barreras en los
lugares donde se une el agua.
5. Se continúa llenando los valles de agua y construyendo barreras para impedir que se
mezcle agua de diferentes colores hasta que todos los picos estén bajo el agua.
6. Cuando todos los picos estén bajo el agua, las barreras que se han creado serán la
segmentación de la imagen.
El siguiente diagrama de flujo ilustra esta explicación:
Visión Artificial Alberto Martínez Montenegro
Página 51 de 58
La aplicación directa de esta idea da unos resultados sobresegmentados debido al ruido que
puedan presentar las imágenes. Para evitar esto, OpenCV implementa un algoritmo basado en
marcadores en el que se especifican cuáles son todos los puntos valle que se fusionarán y cuáles
no lo son. En la documentación de OpenCV lo definen como una “segmentación interactiva”.
La idea detrás del algoritmo meanshift es la siguiente:
1. Seleccionamos (mediante un método de nuestra elección), una región de interés de la
imagen. El objetivo del algoritmo es mover esta región de interés a la zona de mayor
densidad de píxeles similares a los de la propia región.
2. Se encuentra el centroide de la región de interés. (En lugar de la distancia euclídea, ha
de usarse la densidad de píxeles similares)
3. Se mueve la región de interés, haciendo que el centro de la región coincida con el
centroide calculado en el paso anterior.
4. Se repiten los pasos 2 y 3 hasta que el centroide calculado coincida con el centro de la
región, (o la distancia esté por debajo de un umbral de error).
Visión Artificial Alberto Martínez Montenegro
Página 52 de 58
Una vez el algoritmo ha terminado, sabremos a qué máximo local se agrupará la región de
interés a la que se le ha aplicado el algoritmo.
El problema aquí es que si no conocemos de antemano los máximos locales, tendremos que ir
seleccionando aleatoriamente regiones de interés de la imagen e ir aplicándoles el algoritmo.
Este hecho puede provocar la ineficiencia o la inexactitud del algoritmo.
b) Indique ventajas e inconvenientes de cada uno y ponga un ejemplo de uso de
cada método.
Ventajas del algoritmo watershed:
El uso del algoritmo watershed para segmentar una imagen real puede dar como resultado una
segmentación óptima si se escogen los mínimos locales adecuados. Si estuviésemos usando
OpenCV esta elección sería escoger unos marcadores adecuados antes de aplicar
“cv.watershed(img,markers)”. En la explicación del tutorial que se enlaza en el enunciado
pueden verse una serie de pasos (umbralización global, erosión, etc) para la obtención de estos
marcadores.
Desventajas del algoritmo watershed:
El usuario de este algoritmo debe tener saber, en mayor o menor medida, cuáles son las partes
más importantes a segmentar, ya que será necesario algún mecanismo de aportación de
información para que el ruido de la imagen no provoque una sobresegmentación.
Ejemplo de uso del algoritmo watershed:
Se propone como ejemplo la siguiente imagen:
Visión Artificial Alberto Martínez Montenegro
Página 53 de 58
Si intentamos segmentarla directamente usando el algoritmo watershed obtendríamos un
resultado sobresegmentado como el siguiente:
Por lo tanto, debemos crear unos marcadores (mediante diferentes métodos) que nos sirvan para
marcar las zonas que sabemos seguro que forma parte de las regiones a segmentar, las que
sabemos seguros que no, y la zona de incertidumbre:
Visión Artificial Alberto Martínez Montenegro
Página 54 de 58
Si aplicamos el algoritmo haciendo uso de estos marcadores, obtenemos la imagen
correctamente segmentada:
Visión Artificial Alberto Martínez Montenegro
Página 55 de 58
Ventajas del algoritmo meanshift:
El algoritmo meanshift tiene la ventaja de suponer un coste computacional bajo. Además, tal y
como se ha visto en la explicación del anterior apartado, el algoritmo sólo necesita que se le
pase un parámetro, la región de interés. Esto supone una ventaja sobre otros algoritmos como k-
medias, que requiere que se le pase el parámetro K, el cual es crítico para los resultados.
Desventajas del algoritmo meanshift:
Tal y cómo se mencionó en el apartado anterior, si no conocemos de antemano los máximos
locales, tendremos que ir seleccionando aleatoriamente regiones de interés de la imagen e ir
aplicándoles el algoritmo. Este hecho puede provocar la ineficiencia o la inexactitud del
algoritmo.
Por lo tanto, el algoritmo tiene la desventaja de requerir al usuario la elección de unas zonas de
interés adecuadas para la obtención de unos buenos resultados.
Ejemplo de uso del algoritmo meanshift:
El uso más común del algoritmo meanshift es el rastreo de objetos en movimiento en vídeos. De
hecho, la función meanshift de OpenCV no está orientada a la segmentación, si no al rastreo de
objetos en movimiento.
En el siguiente Jupiter Notebook: http://www.chioka.in/meanshift-algorithm-for-the-rest-of-us-
python/ se ha encontrado una implementación del algoritmo en Python.
Haciendo uso de está implementación pueden obtenerse buenos resultados de segmentación,
como en el siguiente ejemplo:
Imagen original:
Visión Artificial Alberto Martínez Montenegro
Página 56 de 58
Imagen segmentada usando meanshift:
c) Comente si realmente se puede considerar que estos algoritmos son algoritmos de
segmentación sin conocimiento del dominio.
Estos algoritmos no se podrían considerar algoritmos de segmentación sin conocimiento del
dominio puros.
En la aplicación práctica del algoritmo watershed hemos visto que el usuario debe tener saber,
en mayor o menor medida, cuáles son las partes más importantes a segmentar, ya que será
necesario algún mecanismo de aportación de información para que el ruido de la imagen no
provoque una sobresegmentación.
En cuanto al algoritmo meanshift, si no conocemos de antemano los máximos locales,
tendremos que ir seleccionando aleatoriamente regiones de interés de la imagen e ir
aplicándoles el algoritmo, y si los conocemos, tendremos que aportar esa información.
Por lo tanto, el algoritmo requiere al usuario la elección de unas zonas de interés adecuadas para
la obtención de unos buenos resultados.
En conclusión, ambos algoritmos requieren, en mayor o menos medida, información sobre el
dominio.
Visión Artificial Alberto Martínez Montenegro
Página 57 de 58
5.4 Utilice el algoritmo más conveniente para segmentar las regiones correspondientes a
los lóbulos temporales del cerebro, lo cual implica separarlas de la región central del
cerebro (tal como aparece en la figura 7)
Tras experimentar con todos los algoritmos, se ha decidido usar el algoritmo watershed para este
apartado. El hecho de que se nos diga que conocemos la sustancia blanca de los lóbulos
temporales y el lóbulo central, nos permitirá crear un marcador que marque las zonas de
sustancia blanca como valles profundos, es decir, zonas en las que se sabe seguro que existen
mínimos locales.
Se copiado el código del tutorial de watershed para OpenCV que se enlaza en el enunciado,
únicamente se han implementado dos diferencias en el código:
• Como nuestra imagen está en tonos grises con un fondo negro, en lugar de usar
cv.THRESH_BINARY_INV en la umbaralización global inicial, se ha usado
cv.THRESH_BINARY
• Dado que se nos dice que conocemos la región de la sustancia blanca, se ha usado como
marcador de zonas seguras la siguiente imagen:
Es decir, se ha sustituido la variable “sure_fg” del código del tutorial, por esa imagen.
Visión Artificial Alberto Martínez Montenegro
Página 58 de 58
Para el resultado obtenido, se ha combinado la imagen original con la imagen segmentada
obtenida con cierto grado de transparencia. Como puede observarse, en los resultados de la
segmentación se distinguen perfectamente las zonas pedidas, aunque el algoritmo ha fallado en
una pequeña parte del lóbulo temporal izquierdo:
Visión Artificial Alberto Martínez Montenegro