Estoy tratando de hacer un poco de procesamiento de imágenes en el iPhone. Estoy usando http://developer.apple.com/library/ios/#qa/qa2010/qa1702.html para capturar los marcos de la cámara.FPS bajo al acceder al buffer de imagen de salida de video del iPhone
Mi problema es que cuando intento acceder al búfer capturado, el FPS de la cámara cae de 30 a aproximadamente 20. ¿Alguien sabe cómo puedo solucionarlo?
Uso la calidad de captura más baja que pude encontrar (AVCaptureSessionPresetLow = 192x144) en formato kCVPixelFormatType_32BGRA. Si alguien conoce una calidad inferior que podría usar, estoy dispuesto a intentarlo.
Cuando hago el mismo acceso a la imagen en otras plataformas, como Symbian, funciona bien.
Aquí está mi código:
#pragma mark -
#pragma mark AVCaptureSession delegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection
{
/*We create an autorelease pool because as we are not in the main_queue our code is
not executed in the main thread. So we have to create an autorelease pool for the thread we are in*/
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
//Lock the image buffer
if (CVPixelBufferLockBaseAddress(imageBuffer, 0) == kCVReturnSuccess)
{
// calculate FPS and display it using main thread
[self performSelectorOnMainThread:@selector(updateFps:) withObject: (id) nil waitUntilDone:NO];
UInt8 *base = (UInt8 *)CVPixelBufferGetBaseAddress(imageBuffer); //image buffer start address
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
int size = (height*width);
UInt8* pRGBtmp = m_pRGBimage;
/*
Here is the problem; m_pRGBimage is RGB image I want to process.
In the 'for' loop I convert the image from BGRA to RGB. As a resault, the FPS drops to 20.
*/
for (int i=0;i<size;i++)
{
pRGBtmp[0] = base[2];
pRGBtmp[1] = base[1];
pRGBtmp[2] = base[0];
base = base+4;
pRGBtmp = pRGBtmp+3;
}
// Display received action
[self performSelectorOnMainThread:@selector(displayAction:) withObject: (id) nil waitUntilDone:NO];
//[self displayAction:&eyePlayOutput];
//saveFrame(imageBuffer);
//unlock the image buffer
CVPixelBufferUnlockBaseAddress(imageBuffer,0);
}
[pool drain];
}
Como complemento a las respuestas, necesito para procesar la imagen en tiempo real, que se está visualizando.
he notado que cuando uso AVCaptureSessionPresetHigh, la cosa más sencilla que hago, como:
for (int i=0;i<size;i++)
x = base[0];
hace que la velocidad de fotogramas para caer a 4-5 FPS. Supongo que es porque una imagen de ese tamaño no está en la memoria caché.
Básicamente necesito una imagen de 96x48. ¿Hay alguna manera simple de reducir la escala de la imagen de salida de la cámara, una forma que utiliza la aceleración del hardware, para poder trabajar con la pequeña?
Estoy de acuerdo en que lo más probable es que el procesamiento lento arrastra toda la captura hacia abajo, pero no estoy seguro de que simplemente liberando el bloqueo pronto haga mucho para ayudar. Para tratar con fotogramas a 30 FPS, la devolución de llamada para cada fotograma deberá completarse en menos de 1/30 de segundo. Si no lo hace, las operaciones de procesamiento simplemente atascarán el hilo en el que se están ejecutando. –
No si funcionó como un patrón de productor-> consumidor, las devoluciones de llamada simplemente se pondrían en cola, todo depende de lo que esté haciendo con la imagen modificada. Si solo lo está guardando, oiga, déjelo en una memoria intermedia en algún lugar. Si se muestra, entonces tiene un problema :) – deanWombourne
He probado el memcpy en un búfer dedicado, pero no sirvió de nada, de hecho fue más lento :( – akaru