Este repositorio contiene la Práctica 3 donde se utilizan técnicas de procesamiento de imágenes con OpenCV para la detección y caracterización geométrica de objetos.
- Práctica 3. Detección y reconocimiento de formas
- Índice
Este proyecto fue desarrollado por:
La tarea consiste en localizar las monedas dentro de una imagen y realizar la suma de sus valores. Para ello, seleccionamos la moneda de 1eur como referencia y el programa logra la funcionalidad deseada de la siguiente manera:
diametros_monedas = {
'1 cent': 16.25,
'2 cent': 18.75,
'5 cent': 21.25,
'10 cent': 19.75,
'20 cent': 22.25,
'50 cent': 24.25,
'1 eur': 23.25,
'2 eur': 25.75
}
Comenzamos con la definición de un diccionario que almacena los diámetros reales de diferentes monedas en milímetros.
scale_width = screen_width / width
scale_height = screen_height / height
scale = min(scale_width, scale_height)
imagen_redimensionada = cv2.resize(imagen, (new_width, new_height), interpolation=cv2.INTER_AREA)
El tamaño de la imagen se ajusta para que quepa en una ventana con dimensiones predeterminadas (1280x720), manteniendo la relación de aspecto.
imgGris = cv2.cvtColor(imagen_redimensionada, cv2.COLOR_BGR2GRAY)
imgGris_suavizada = cv2.GaussianBlur(imgGris, (11, 11), 2)
Se convierte la imagen a escala de grises para simplificar la detección de bordes. Luego, se aplica un suavizado Gaussian Blur para reducir el ruido en la imagen.
monedasDetectadas = cv2.HoughCircles(
imgGris_suavizada,
cv2.HOUGH_GRADIENT,
dp=1,
minDist=100,
param1=100,
param2=60,
minRadius=40,
maxRadius=150
)
Se utiliza el método HoughCircles
para detectar los círculos (monedas) en la imagen. Esta función busca patrones circulares y detecta sus posiciones y radios.
coins = []
for i in monedasDetectadas[0, :]:
coin = {
'center': (i[0], i[1]),
'radius': i[2],
'value': None,
'diameter_px': i[2] * 2
}
coins.append(coin)
Los datos de las monedas detectadas se almacenan en una lista de diccionarios, donde se registra el centro, radio y diámetro en píxeles de cada moneda.
def onclick(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
for coin in coins:
dx = x - coin['center'][0]
dy = y - coin['center'][1]
distancia_cuadrada = dx ** 2 + dy ** 2
if distancia_cuadrada <= coin['radius'] ** 2:
print("Moneda seleccionada como referencia (1 EUR)")
pixel_mm_ratio = coin['diameter_px'] / diametros_monedas['1 eur']
identificar_monedas()
break
Se define una función que detecta clics del usuario en la imagen. Cuando el usuario hace clic sobre una moneda, esta se toma como referencia (moneda de 1 EUR) y se calcula la relación píxeles/mm.
def identificar_monedas():
for coin in coins:
if coin['value'] is None:
diametro_mm = coin['diameter_px'] / pixel_mm_ratio
idx = (np.abs(diametros_reales - diametro_mm)).argmin()
coin['value'] = valores_monedas[idx]
print(f"Moneda identificada: {coin['value']}")
Una vez que se ha seleccionado una moneda de referencia, el programa calcula el tamaño de las otras monedas y las compara con los diámetros conocidos para identificar su valor.
total_sum = 0
for coin in coins:
if coin['value'] is not None:
value_str = coin['value']
if 'cent' in value_str:
value = int(value_str.split(' ')[0]) / 100
elif 'eur' in value_str:
value = float(value_str.split(' ')[0])
total_sum += value
Se calcula y muestra la suma total del valor de todas las monedas detectadas.
En esta tarea abordamos la clasificación de partículas encontradas en playas de Canarias, centrándonos en tres categorías: fragmentos plásticos, pellets y alquitrán. Utilizamos imágenes de cada categoría para extraer características geométricas y de apariencia que faciliten su clasificación.
Puede ejecutar el cuaderno de Jupyter VC_P3_T2.ipynb
para ver el código y los resultados detallados.
Trabajamos con tres imágenes, cada una correspondiente a una categoría específica:
- Fragmentos: Plásticos de menos de 5 mm (microplásticos).
- Pellets: Partículas esféricas plásticas de menos de 5 mm.
- Alquitrán: Restos de petróleo comunes en las playas.
- Conversión a Escala de Grises: Simplificamos las imágenes para el procesamiento.
- Desenfoque Gaussiano: Reducimos el ruido y mejoramos la segmentación.
- Apertura Morfológica: Eliminamos pequeños objetos y ruido residual.
- Umbralización de Otsu: Segmentamos las partículas del fondo.
- Inversión de Imágenes: Aseguramos que las partículas sean blancas sobre fondo negro.
- Encontrar Contornos: Identificamos los contornos de las partículas.
- Filtrado por Área: Eliminamos contornos que no corresponden a partículas reales estableciendo umbrales de área.
Para cada partícula detectada, extraemos:
- Área
- Perímetro
- Compacidad (
C = P² / A
) - Relación de Aspecto (ancho/alto)
- Extensión (área de la partícula / área del contenedor)
- Relación de Ejes de la Elipse Ajustada
- Clasificador Basado en Reglas: Implementamos un clasificador manual utilizando umbrales derivados del análisis estadístico.
- Asignación de Etiquetas: Clasificamos cada partícula en una de las tres categorías.
- Matriz de Confusión: Evaluamos el rendimiento del clasificador.
- Informe de Clasificación: Calculamos métricas como precisión, recall y F1-score.
- OpenCV Documentation: https://docs.opencv.org/
- NumPy Documentation: https://numpy.org/doc/
- Matplotlib Documentation: https://matplotlib.org/stable/contents.html
- OpenCV Documentation: docs.opencv.org
- NumPy Documentation: numpy.org/doc