Procesamiento Audiovisual
Sesión 3. Entrada/salida avanzada con HighGUI
Guión de Prácticas
Procesamiento Audiovisual
3º II/ITIS
Guión de prácticas
HighGUI
HighGUI
Sesión 3. Entrada/salida avanzada con HighGUI
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
Indicaciones finales
DESCRIPCIÓN
cvReleaseImage), que son de tipo IplImage*.
cvSaveImage).
• 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 (cvCreateImage, cvCloneImage,
o Funciones de lectura/escritura de ficheros de imágenes (cvLoadImage,
o Operaciones de creación y uso de ventanas (cvNamedWindow,
o Acceso a los píxeles de las imágenes (cvGet2D, cvSet2D).
o Entrada de teclado (cvWaitKey).
cvShowImage, cvDestroyWindow).
• 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 IplImage*. Estas ventanas son referenciadas con
1
Procesamiento Audiovisual
Sesión 3. Entrada/salida avanzada con HighGUI
Guión de Prácticas
cadenas de texto (“Entrada”, “Salida”, “Ventana 3”, etc.) dentro del programa. Las
ventanas se crean con cvNamedWindow(nombre, flag).
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. En HighGUI2 se añade el evento CV_EVENT_CLOSE.
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
cvSetMouseCallback 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:
cvNamedWindow("Salida", 0); // Creamos la ventana
cvSetMouseCallback("Salida", mouseCallBack, NULL); // Asociar cb
la
El tercer parámetro de cvSetMouseCallback 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:
IplImage *img= NULL;
2
Procesamiento Audiovisual
Guión de Prácticas
Sesión 3. Entrada/salida avanzada con HighGUI
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):
void mousecb (int event, int x, int y, int flags, void *param)
{
if (flags==CV_EVENT_FLAG_LBUTTON) {// Si está pulsado el ratón
cvCircle(img, cvPoint(x, y), 10, CV_RGB(255,0,0), -1);
cvShowImage("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= cvLoadImage(nombre.toAscii());
if (!img) return;
cvNamedWindow("Salida", 0);
cvSetMouseCallback("Salida", mousecb, NULL);
cvShowImage("Salida", img);
}
10. Guardar, ejecutar y ver el resultado.
11. Ojo: el programa anterior no libera la memoria correctamente. Modificarlo para que
no se pierda memoria en ningún caso.
12. Nota: por algún extraño motivo, la librería HighGUI no emite los eventos de doble
clic del ratón (CV_EVENT_LBUTTONDBLCLK, _RBUTTONDBLCLK, etc.).
BARRAS DE POSICIÓN DE HIGHGUI (VER EN CASA)
13. 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.
14. Las funciones relacionadas con las barras de posición son:
•
int cvCreateTrackbar (const char* trackbar_name, const char*
window_name, int* value, int count, CvTrackbarCallback on_change);
Añade una barra de posición a
la ventana con nombre
window_name.
La barra se identifica con la cadena trackbar_name.
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
3
Procesamiento Audiovisual
Sesión 3. Entrada/salida avanzada con HighGUI
Guión de Prácticas
on_change, cuya cabecera es: void nombre (int valor). Si no se
necesita podemos poner NULL.
•
int cvGetTrackbarPos (const char* trackbar_name, const char*
window_name);
Obtiene el valor actual de la barra de posición con nombre
trackbar_name dentro de la ventana con nombre window_name.
Realmente no es necesaria. Recordar que al crear la ventana se
indica un puntero a un sitio (un entero) donde se almacenará el
valor.
• void cvSetTrackbarPos (const char* trackbar_name, const char*
window_name, int pos);
Establecer a pos el valor actual de la barra de posición con nombre
trackbar_name dentro de la ventana con nombre window_name.
AJUSTANDO EL TAMAÑO DEL PINCEL
15. 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.
16. En primer lugar, añadimos una variable global radioPincel.
17. Dentro del formulario, insertamos un QSlider y una etiqueta con el texto "Tamaño
int radioPincel= 1; // Variable global, definida antes del cb
del pincel". En el slot valueChanged del QSlider escribimos:
radioPincel= value;
18. Modificamos también el callback del ratón, para que dibuje el círculo según el radio
seleccionado.
...
cvCircle(img, cvPoint(x, y), radioPincel, CV_RGB(255,0,0), -1);
...
19. 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...
20. 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; (iii) la mostramos en pantalla; y (iv) liberamos la copia.
void mousecb (int event, int x, int y, int flags, void *param)
{
if (flags==CV_EVENT_FLAG_LBUTTON) { // Si está pulsado el ratón
cvCircle(img, cvPoint(x, y), radioPincel, CV_RGB(255,0,0), -1);
cvShowImage("Salida", img);
}
4
Procesamiento Audiovisual
Sesión 3. Entrada/salida avanzada con HighGUI
Guión de Prácticas
else { // Si no está pulsado el ratón
IplImage *res= cvCloneImage(img);
cvCircle(res, cvPoint(x, y), radioPincel, CV_RGB(255,255,255));
cvShowImage("Salida", res);
cvReleaseImage(&res);
}
}
21. Ejecutar y ver el resultado.
SELECCIONANDO EL COLOR DEL PINCEL
22. 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.
Comentarios de: Procesamiento Audiovisual - Sesión 3 Entrada/salida avanzada con HighGUI (0)
No hay comentarios