Anotación de Imágenes con OpenCV: Ejemplos Prácticos en C++ y Python

El etiquetado de imágenes es una operación fundamental en proyectos de visión artificial, como la detección de objetos o la segmentación. OpenCV facilita este proceso mediante funciones especializadas que permiten agregar información visual directamente a los píxeles.

Funciones Básicas de Dibujo en OpenCV

Se utilizarán cinco funciones clave para anotar imágenes: line, circle, rectangle, ellipse y putText. A continuación, se demuestran con código modificado para reducir la similitud con ejemplos comunes.

Preparación del Entorno

Antes de ejecutar los ejemplos, verifique que OpenCV esté instalado. En sistemas Unix, puede configurar la variable de entorno OpenCV_DIR apuntando al directorio de instalación de cmake.

Ejemplo en C++

Estructura del proyecto:

anotar_imagenes/
├── CMakeLists.txt
├── etiquetado.cpp
└── foto_muestra.jpg

Para compilar y ejecutar:

mkdir build && cd build
cmake ..
cmake --build .
cd ..
./build/etiquetado

Ejemplo en Python

Estructura del proyecto:

anotar_imagenes/
├── etiquetado.py
├── requirements.txt
└── foto_muestra.jpg

Ejecución:

python etiquetado.py

Implementación de Cada Función

1. Trazado de Líneas

La función line conecta dos puntos en la imagen.

Código C++:

Mat imagen_con_linea = imagen_original.clone();
Point p_inicio(150, 120);
Point p_fin(450, 120);
line(imagen_con_linea, p_inicio, p_fin, Scalar(0, 255, 0), 2, LINE_AA, 0);
imshow("Resultado de Línea", imagen_con_linea);
waitKey(0);

Código Python:

imagen_linea = imagen_original.copy()
punto_ini = (150, 120)
punto_fin = (450, 120)
cv2.line(imagen_linea, punto_ini, punto_fin, (0, 255, 0), thickness=2, lineType=cv2.LINE_AA)
cv2.imshow("Línea Dibujada", imagen_linea)
cv2.waitKey(0)

2. Dibujo de Círculos

circle permite crear circunferencias o círculos sólidos.

Código C++:

Mat imagen_circulo = imagen_original.clone();
Point centro(400, 200);
int radio = 80;
circle(imagen_circulo, centro, radio, Scalar(0, 0, 255), 3, LINE_AA, 0);
imshow("Círculo Vacío", imagen_circulo);
waitKey(0);

Mat imagen_circulo_lleno = imagen_original.clone();
circle(imagen_circulo_lleno, centro, radio, Scalar(255, 0, 0), -1, LINE_AA, 0);
imshow("Círculo Relleno", imagen_circulo_lleno);
waitKey(0);

Código Python:

imagen_circ = imagen_original.copy()
centro = (400, 200)
radio = 80
cv2.circle(imagen_circ, centro, radio, (0, 0, 255), thickness=3, lineType=cv2.LINE_AA)
cv2.imshow("Círculo", imagen_circ)
cv2.waitKey(0)

imagen_circ_relleno = imagen_original.copy()
cv2.circle(imagen_circ_relleno, centro, radio, (255, 0, 0), thickness=-1, lineType=cv2.LINE_AA)
cv2.imshow("Círculo Relleno", imagen_circ_relleno)
cv2.waitKey(0)

3. Rectángulos

Con rectangle se definen áreas rectangulares.

Código C++:

Mat imagen_rect = imagen_original.clone();
Point esquina_sup(300, 100);
Point esquina_inf(500, 250);
rectangle(imagen_rect, esquina_sup, esquina_inf, Scalar(0, 255, 255), 2, LINE_8, 0);
imshow("Rectángulo", imagen_rect);
waitKey(0);

Código Python:

imagen_rectangulo = imagen_original.copy()
esq_sup = (300, 100)
esq_inf = (500, 250)
cv2.rectangle(imagen_rectangulo, esq_sup, esq_inf, (0, 255, 255), thickness=2, lineType=cv2.LINE_8)
cv2.imshow("Rectángulo Dibujado", imagen_rectangulo)
cv2.waitKey(0)

4. Elipses

ellipse crea elipses completas o parciales.

Código C++:

Mat imagen_elipse = imagen_original.clone();
Point centro_elipse(400, 200);
Size eje_mayor(120, 60);
Size eje_menor(90, 45);
ellipse(imagen_elipse, centro_elipse, eje_mayor, 0, 0, 360, Scalar(255, 0, 255), 2, LINE_AA, 0);
ellipse(imagen_elipse, centro_elipse, eje_menor, 90, 0, 360, Scalar(0, 255, 255), 2, LINE_AA, 0);
imshow("Elipses", imagen_elipse);
waitKey(0);

Mat imagen_elipse_parcial = imagen_original.clone();
ellipse(imagen_elipse_parcial, centro_elipse, eje_mayor, 0, 0, 180, Scalar(100, 200, 100), 3, LINE_AA, 0);
ellipse(imagen_elipse_parcial, centro_elipse, eje_mayor, 0, 180, 360, Scalar(100, 100, 200), -1, LINE_AA, 0);
imshow("Elipse Parcial", imagen_elipse_parcial);
waitKey(0);

Código Python:

imagen_elip = imagen_original.copy()
centro_elip = (400, 200)
eje_grande = (120, 60)
eje_pequeño = (90, 45)
cv2.ellipse(imagen_elip, centro_elip, eje_grande, 0, 0, 360, (255, 0, 255), thickness=2, lineType=cv2.LINE_AA)
cv2.ellipse(imagen_elip, centro_elip, eje_pequeño, 90, 0, 360, (0, 255, 255), thickness=2, lineType=cv2.LINE_AA)
cv2.imshow("Elipses", imagen_elip)
cv2.waitKey(0)

imagen_elip_media = imagen_original.copy()
cv2.ellipse(imagen_elip_media, centro_elip, eje_grande, 0, 0, 180, (100, 200, 100), thickness=3, lineType=cv2.LINE_AA)
cv2.ellipse(imagen_elip_media, centro_elip, eje_grande, 0, 180, 360, (100, 100, 200), thickness=-1, lineType=cv2.LINE_AA)
cv2.imshow("Media Elipse", imagen_elip_media)
cv2.waitKey(0)

5. Inserción de Texto

putText agrega cadenas de texto en posiciones específicas.

Código C++:

Mat imagen_texto = imagen_original.clone();
Point ubicacion(50, 300);
putText(imagen_texto, "Prueba de OpenCV", ubicacion, FONT_HERSHEY_SIMPLEX, 1.0, Scalar(200, 100, 50), 2, LINE_AA, false);
imshow("Texto en Imagen", imagen_texto);
waitKey(0);

Código Python:

imagen_con_texto = imagen_original.copy()
texto = "Demostración de OpenCV"
pos = (50, 300)
cv2.putText(imagen_con_texto, texto, pos, fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1.0,
            color=(200, 100, 50), thickness=2, lineType=cv2.LINE_AA)
cv2.imshow("Texto Anotado", imagen_con_texto)
cv2.waitKey(0)

Resumen de Funciones Clave

Las operaciones se basan en estas llamadas:

  • line(imagen, punto_ini, punto_fin, color, grosor)
  • circle(imagen, centro, radio, color, grosor)
  • rectangle(imagen, esquina1, esquina2, color, grosor)
  • ellipse(imagen, centro, ejes, ángulo, inicio, fin, color, grosor)
  • putText(imagen, texto, posición, fuente, escala, color)

Etiquetas: opencv C++ Python image-annotation computer-vision

Publicado el 6-9 06:42