reproducir read from con abrir c++ ios objective-c opencv

c++ - read - reproducir video con opencv



Simular una larga exposición de los cuadros de video OpenCV (3)

El siguiente enfoque debería funcionar en un caso donde

  • tienes un fondo conocido (o aprendido)
  • Puede segmentar el movimiento para obtener una máscara para el primer plano.

Supongamos que obtuviste dicho fondo y puedes obtener una máscara de primer plano para cada cuadro que capturas después de la etapa de aprendizaje de fondo. Vamos a denotar

  • el fondo aprendido como bg
  • marco en el tiempo t como I_t
  • Máscara de primer plano correspondiente para I_t as fgmask_t

Luego actualiza el fondo para cada cuadro como

I_t.copyTo (bg, fgmask_t)

donde copyTo es un método de la clase Mat de OpenCV.

Así que el procedimiento sería

Learn bg for each frame I_t { get fgmask_t I_t.copyTo(bg, fgmask_t) }

Cuando finaliza la captura de cuadros, bg contendrá el historial de movimiento.

Puede usar un Modelo de Mezcla Gaussiana (variantes de BackgroundSubtractorMOG en OpenCV) o una técnica simple de diferenciación de cuadros para esto. La calidad dependerá de qué tan bien la técnica segmenta el movimiento (o la calidad de la máscara de primer plano).

Creo que esto debería funcionar bien para una cámara estacionaria, pero si la cámara se mueve, puede que no funcione muy bien, excepto en una situación en la que la cámara rastrea un objeto.

Estoy tratando de simular una foto de larga exposición combinando imágenes (cuadros) en una imagen y realizando operaciones basadas en un alfa preestablecido. Estoy haciendo esto en un iPhone, y actualmente tengo la duración del video configurado en 1 segundo (30 fotogramas). El alfa se establece en 1.0/frameCount sin embargo, codifiqué en 30 para representar un segundo de la captura de video de 30 FPS. Detengo las operaciones una vez que ha alcanzado un segundo de video / 30 cuadros. La idea es que el usuario pueda configurar un temporizador para x segundos y haré los cálculos para determinar cuántos fotogramas permitir.

Aquí está el código que estoy usando:

- (void)processImage:(Mat&)image { if (_isRecording) { // first frame double alpha = 1.0/30; if (_frameCount == 0) { _exposed = image; _frameCount++; } else { Mat exposed = _exposed.clone(); addWeighted(exposed, alpha, image, 1.0 - alpha, 0.0, _exposed); _frameCount++; } // stop and save image if (_frameCount == 30) { _isRecording = NO; _frameCount = 0; cvtColor(_exposed, _exposed, CV_BGRA2RGB, 30); UIImage *exposed = [LEMatConverter UIImageFromCVMat:_exposed]; UIImageWriteToSavedPhotosAlbum(exposed, nil, nil, nil); NSLog(@"saved"); } } }

Cuando ejecuto este código, básicamente recupero una imagen fija que parece un solo fotograma. Aquí hay un ejemplo:

¿Alguien sabe cómo puedo producir el efecto deseado de una imagen de larga exposición a partir de cuadros de video dado que sé cuántos cuadros habrá?


En mi opinión, usar alfa no es la forma correcta.

Debe acumular las diferencias (absolutas) del marco de exposición:

if (_frameCount == 0) { _exposed = image.clone(); } else { _exposed += image - _exposed; }


En primer lugar, (probablemente este no sea su caso, ya que señaló que está trabajando en un video y no en una cámara) si basa su código en el valor de la velocidad de cuadros, asegúrese de que 30 fps sea el valor efectivo y No el máximo. A veces, las cámaras ajustan automáticamente ese número según la cantidad de luz que reciben del entorno. Si está oscuro, el tiempo de exposición aumenta y, por lo tanto, la tasa de cuadros disminuye.

Segundo punto, es realmente difícil simular el mecanismo real de exposición de la foto dado un montón de píxeles. Imagina que quieres duplicar el tiempo de exposición, esto debería ser simulado por dos cuadros consecutivos. En el mundo real, duplicar el tiempo de exposición significa que la velocidad de obturación se reduce a la mitad y, por lo tanto, el doble de luz llega al sensor o la película, lo que resulta en una imagen más brillante.
¿Cómo simulas esto? Considere por simplicidad el caso de dos imágenes en escala de grises bastante brillantes que desea combinar. Si en un punto dado los valores de píxeles son, digamos, 180 y 181, ¿cuál es el valor resultante? La primera respuesta sería 180 + 181, pero las intensidades de píxeles oscilan entre 0 y 255, por lo que se debe truncar en 255. La cámara real con mayor exposición probablemente se comportaría de manera diferente, no alcanzando el valor máximo.

Ahora voy a considerar tu código.
La primera vez que procesa una imagen (es decir, ejecuta la función), simplemente almacena el marco en la variable _expuesta.
La segunda vez, combina 29/30 del nuevo marco y 1/30 de la imagen almacenada anteriormente.
La tercera vez 29/30 del tercer cuadro con el resultado de la operación anterior. Esto da como resultado la colocación de un peso de desvanecimiento en el primer cuadro que prácticamente desaparece.
La última vez que llama a la función, nuevamente, suma 29/30 del último fotograma y 1/30 del resultado anterior. A su vez, esto significa que el efecto de los primeros cuadros desaparece virtualmente e incluso el anterior cuenta solo para una participación de 29 / (30x30). La imagen que obtienes es solo el último fotograma con un ligero desenfoque proveniente de los fotogramas anteriores.
¿Cómo se obtiene una simulación de la exposición? Si simplemente quiere promediar 30 marcos, debe reemplazar estas líneas:

if (_frameCount == 0) { _exposed = image.clone(); addWeighted(_exposed, 0.0, image, alpha, 0.0, _exposed); } else { addWeighted(_exposed, 1.0, image, alpha, 0.0, _exposed); } _frameCount++;

Si también desea que la imagen sea más brillante hasta cierto punto, puede simularla mediante un factor de multiplicación:

if (_frameCount == 0) { _exposed = image.clone(); addWeighted(_exposed, 0.0, image, alpha*brightfactor, 0.0, _exposed); } else { addWeighted(_exposed, 1.0, image, alpha*brightfactor, 0.0, _exposed); } _frameCount++;

Ajuste el factor de brillo a un valor que simule mejor un aumento real en el tiempo de exposición. (EDITAR: un valor entre 1.5 y 2.5 debe hacer el trabajo)