Procesamiento de Imágenes
Sesión 3. Entrada/salida avanzada con HighGUI
Guión de Prácticas
Procesamiento de Imágenes
Máster NTI
HighGUI
HighGUI
Guión de prácticas
Descripción
Eventos del ratón
Un sencillo pintor
Barras de posición
Tamaño del pincel
Color del pincel
Entrada de vídeo
Escribir vídeo
Sesión 3. Entrada/salida avanzada con HighGUI
DESCRIPCIÓN
Indicaciones finales
La librería HighGUI de OpenCV resuelve un gran número de problemas
relacionados con la entrada/salida y con el interface de usuario. En la sesión
anterior estudiamos:
o Funciones de creación de imágenes (create, clone), que son de tipo Mat.
o Funciones de
imágenes (imread,
lectura/escritura de
ficheros de
imwrite).
o Operaciones de creación y uso de ventanas (namedWindow, imshow,
destroyWindow).
o Acceso a los píxeles de las imágenes (at).
o Entrada de teclado (waitKey).
Ahora vamos a ver más funcionalidades avanzadas de E/S. Veremos cosas
interesantes que se pueden hacer con las ventanas de HighGUI y el manejo de
vídeo (de cámara y de archivos).
Una utilidad muy importante es la capacidad de asignar acciones a los eventos
del ratón sobre las ventanas de HighGUI. Los eventos serán: pasar el ratón
por encima, hacer clic en la ventana, cerrar la ventana, etc. Las acciones son
procedimientos que implementamos nosotros, los denominados callback.
Otra funcionalidad son las barras de posición, TrackBar, que se pueden añadir
a las ventanas, para pedir al usuario una entrada numérica. Los eventos de las
barras de posición también pueden tener un callback asociado.
Finalmente, HighGUI ofrece funciones para entrada de vídeo (desde cámara y
desde archivos AVI, MPG, WMV y MOV, según los codecs instalados en el
sistema) y salida de vídeo (en formato AVI).
HIGHGUI Y EVENTOS DEL RATÓN
1. Recordatorio: HighGUI permite crear ventanas en tiempo de ejecución para
mostrar imágenes, de tipo Mat. Estas ventanas son referenciadas con cadenas de
texto (“Entrada”, “Salida”, “Ventana 3”, etc.) dentro del programa. Las ventanas se
crean con namedWindow(nombre, flag).
1
Procesamiento de Imágenes
Sesión 3. Entrada/salida avanzada con HighGUI
Guión de Prácticas
2. Las ventanas de HighGUI pueden tener código asociado a los eventos del ratón,
ya sea pulsar un botón o simplemente pasar con el ratón por encima de la ventana.
El código asociado a los eventos del ratón es un procedimiento (denominado en
inglés “call back”).
3. En HighGUI, todos los eventos de una ventana llaman al mismo callback, que debe
tener la siguiente cabecera:
void mouseCallBack (int event, int x, int y, int flags, void* param);
Donde:
(x, y) indica la posición del ratón sobre la imagen al producirse el evento.
event es el tipo de evento que ha ocurrido: CV_EVENT_[MOUSEMOVE,
LBUTTONDOWN, RBUTTONDOWN, MBUTTONDOWN, LBUTTONUP],
etc.
flags indica el estado de pulsación de los botones:
CV_EVENT_FLAG_[LBUTTON, RBUTTON, MBUTTON, CTRLKEY,
SHIFTKEY, ALTKEY].
param es un parámetro opcional definido por el usuario al asociar a la
ventana el callback.
El cuerpo del procedimiento lo escribimos nosotros, según lo que necesitemos.
4. Una vez definido el procedimiento mouseCallBack, utilizamos
función
setMouseCallback para indicar que en caso de producirse cualquier evento del
ratón en una ventana dada, se ejecute el procedimiento definido; es decir, para
asociar el callback. Tendríamos algo como lo siguiente:
la
namedWindow("Salida", 0); // Creamos la ventana
setMouseCallback("Salida", mouseCallBack, NULL); // Asociamos callback
El tercer parámetro de setMouseCallback es el valor param que recibe el callback
al ser invocado.
UN SENCILLO PINTOR MONOCROMO
5. Vamos a crear un sencillo proyecto que maneje callbacks del ratón. Inicialmente
permitirá abrir una imagen y pintar círculos rojos. Luego vamos a ir mejorándolo.
6. Abrir Qt Creator, crear un proyecto nuevo de tipo QMainWindow (ver la sesión 1)
y prepararlo para poder usar OpenCV (ver la sesión 2).
7. Nuestro programa trabajará en todo momento con una imagen, sobre la cual
pintamos, mostramos en la ventana, guardamos a disco, etc. Por lo tanto, nos
debemos definir una variable global al principio de mainwindow.cpp:
Mat img;
8. Vamos a crear un callback que pinte un círculo en img cuando pinchemos con el
ratón. Definimos el siguiente procedimiento en mainwindow.cpp (fuera de la clase):
2
Procesamiento de Imágenes
Sesión 3. Entrada/salida avanzada con HighGUI
Guión de Prácticas
void mousecb (int event, int x, int y, int flags, void *param)
{
if (flags==CV_EVENT_FLAG_LBUTTON) { // Si está pulsado el ratón
circle(img, Point(x, y), 10, CV_RGB(255,0,0), -1);
imshow("Salida", img);
}
}
9. Ahora añadimos un botón "Abrir imagen" en el formulario y creamos el slot
clicked, que leerá una imagen de disco, la mostrará en la ventana "Salida" y
asociará el callback a la ventana.
void MainWindow::on_pushButton_clicked()
{
QString nombre= QFileDialog::getOpenFileName();
img= imread(nombre.toLatin1().data());
if (img.empty()) return;
namedWindow("Salida", 0);
setMouseCallback("Salida", mousecb, NULL);
imshow("Salida", img);
}
10. Guardar, ejecutar y ver el resultado. ¿Qué falta?
BARRAS DE POSICIÓN DE HIGHGUI (VER EN CASA)
11. A las ventanas de HighGUI también se le pueden asociar barras de posición
(TrackBar), que permiten al usuario elegir un valor entre 0 y cierto máximo. Igual
que las ventanas, cada barra se identifica con una cadena de texto en el programa.
Se puede asociar un evento al cambio de su valor.
12. Las funciones relacionadas con las barras de posición son:
int createTrackbar (string trackbarName, string winName, int* value,
int count, TrackbarCallback onChange=0, void* userdata=0);
Añade una barra de posición a la ventana con nombre winName.
La barra se identifica con la cadena trackbarName.
Las barras aparecen arriba, dentro de la ventana.
Su valor está entre 0 y count. El valor actual se guarda en el
entero apuntado por value.
Es posible asociar un evento a la modificación del valor (es decir,
cuando el usuario lo cambia). El evento será el parámetro
onChange, cuya cabecera es: void nombre (int valor, void *ptr).
Si no se necesita callback podemos poner NULL.
int getTrackbarPos (string trackbarName, string winName);
Obtiene el valor actual de la barra de posición con nombre
trackbarName dentro de la ventana con nombre winName.
Realmente no es necesaria. Recordar que al crear la ventana se
indica un puntero a un sitio (un entero) donde se almacena el valor.
void setTrackbarPos (string trackbarName, string winName, int pos);
Establecer a pos el valor actual de la barra de posición con nombre
trackbarName dentro de la ventana con nombre winName.
3
Procesamiento de Imágenes
Sesión 3. Entrada/salida avanzada con HighGUI
Guión de Prácticas
AJUSTANDO EL TAMAÑO DEL PINCEL
13. Vamos a modificar el programa anterior para permitir que el usuario pueda
seleccionar el tamaño del pincel con el que se pinta. Aunque podemos usar los
TrackBar de HighGUI, vamos a hacerlo con un QSlider de Qt.
14. En primer lugar, añadimos una variable global radioPincel.
int radioPincel= 10; // Variable global, definida antes del callback
15. Dentro del formulario, insertamos un componente Horizontal Slider y una etiqueta
con el texto "Tamaño del pincel". En el slot valueChanged del Slider escribimos:
void MainWindow::on_horizontalSlider_valueChanged(int value)
{
radioPincel= value;
}
16. Modificamos también el callback del ratón, para que dibuje el círculo según el radio
seleccionado.
...
circle(img, Point(x, y), radioPincel, CV_RGB(255,0,0), -1);
...
17. Guardamos y ejecutamos. Muy bien, el programa nos permite cambiar el tamaño...
pero es difícil dibujar, porque no sabemos de qué tamaño va a salir el punto...
18. Vamos a mejorar el callback del ratón, para que se muestre el tamaño del pincel
pero sin modificar la imagen. Por lo tanto: (i) clonamos la imagen img; (ii) pintamos
el círculo en la copia; y (iii) la mostramos en pantalla.
void mousecb (int event, int x, int y, int flags, void *param)
{
if (flags==CV_EVENT_FLAG_LBUTTON) { // Si está pulsado el ratón
circle(img, Point(x, y), radioPincel, CV_RGB(255,0,0), -1);
imshow("Salida", img);
}
else { // Si no está pulsado el ratón
Mat res= img.clone();
circle(res, Point(x, y), radioPincel, CV_RGB(255,255,255));
imshow("Salida", res);
}
}
19. Ejecutar y ver el resultado.
SELECCIONANDO EL COLOR DEL PINCEL
20. El siguiente paso para conseguir una herramienta casi profesional es permitir que
se pueda seleccionar el color del pincel. En primer lugar, añadimos una variable
global en el mismo sitio donde está el tamaño del pincel.
4
Procesamiento de Imágenes
Sesión 3. Entrada/salida avanzada con HighGUI
Mat img;
int radioPincel= 10;
Scalar colorPincel= CV_RGB(255,0,0);
21. En el callback del ratón, cambiamos el primer circle por:
Guión de Prácticas
...
circle(img, Point(x, y), radioPincel, colorPincel, -1);
...
22. Añadimos un botón nuevo al formulario, que lo llamamos "Color". En el slot
asociado a este botón debemos: (i) abrir un cuadro de diálogo de color
(QColorDialog);
Comentarios de: Procesamiento Audiovisual - Sesión 3 Entrada/salida avanzada con HighGUI (0)
No hay comentarios