IBCBiomech / insolesibc

Prototipo de aplicación para plantillas
0 stars 1 forks source link

Grabación dos webcams #12

Closed ivanjimenez closed 1 year ago

ivanjimenez commented 1 year ago

El caso de uso sería que una vez escaneadas las plantillas y cámaras. Se puedan abrir o ninguna, o una o dos cámaras. Cada cámara tendrá un título que será "Body Cam" y "Foot Cam". Cada una de estas cámaras tendrá una casilla de verificación para seleccionarla como grabación. Esto permitirá que el usuario pueda ver ambas cámaras y seleccionar que se almacene cualquiera de ellas o sólo una o ninguna.

Image

bernatDiaz commented 1 year ago

Al abrir 2 camaras a la vez (solo abrir, no estoy grabando aun) se ralentiza mucho la aplicacion.

El callback de la camara es este:

private async Task displayCameraCallback()
        {
            while (true)
            {
                if (cancellationTokenDisplay.IsCancellationRequested)
                {
                    videoCapture.Release();
                    videoCapture = null;
                    currentFrame = getBlackImage();
                    await Dispatcher.BeginInvoke(DispatcherPriority.Normal, () =>
                    {
                        imgViewport.Source = BitmapSourceConverter.ToBitmapSource(getBlackImage());
                    });
                    cameraChanged?.Invoke(this, EventArgs.Empty);
                    return;
                }
                //Mat frame = new Mat();
                videoCapture.Read(currentFrame);
                if (!currentFrame.Empty())
                {
                    //currentFrame = frame;
                    await Dispatcher.BeginInvoke(DispatcherPriority.Normal, () =>
                    {
                        imgViewport.Source = BitmapSourceConverter.ToBitmapSource(currentFrame);
                    }
                    );
                }
                await Task.Delay(1000 / Config.VIDEO_FPS);
            }
        }

Instancio la misma clase en 2 frames distintos (la clase es una Page)

bernatDiaz commented 1 year ago

LLamo la callback asi:

displayTask = displayCameraCallback();
bernatDiaz commented 1 year ago

Lo importante es esto:

                videoCapture.Read(currentFrame);
                if (!currentFrame.Empty())
                {
                    //currentFrame = frame;
                    await Dispatcher.BeginInvoke(DispatcherPriority.Normal, () =>
                    {
                        imgViewport.Source = BitmapSourceConverter.ToBitmapSource(currentFrame);
                    }
                    );
                }
                await Task.Delay(1000 / Config.VIDEO_FPS);

lo de arriba se ejecuta cuando se para

if (cancellationTokenDisplay.IsCancellationRequested)
ivanjimenez commented 1 year ago

Si, en teoría con el await debería realizar todo asíncrono. si lanzas un método

displayTask = displayCameraCallback();

Yo metería todo el callback (private async Task displayCameraCallback()) en una tarea asíncrona.

await Task.Run(() => displayCameraCallback();

Yo usé hilos para python y funcionaba correctamente. Pero intentemos utilizar las tasks en C# a ver cómo funcionan.

bernatDiaz commented 1 year ago

Vale, ahora va mucha mejor

ivanjimenez commented 1 year ago

El tema es que tienes un loop infinito que es una long task. Da igual que tengas un await, el propio loop ya es suficiente para que se bloquee la GUI. Yo lo soluciono con eso y así con opencv lo hacen, tiran el proceso en un hilo y ya está.

No sé si es lo mejor de todas formas, pero funciona. Otra cosa no sé si el opencv te permite multicam. Que tal vez eso ayude y tengan implementado por debajo la gestión de hilos.

ivanjimenez commented 1 year ago

Comprobado