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)