iphone objective-c uiview avfoundation

iphone - ¿Es posible representar AVCaptureVideoPreviewLayer en un contexto de gráficos?



objective-c uiview (2)

Esto parece una tarea simple, pero me está volviendo loco. ¿Es posible convertir una UIView que contenga AVCaptureVideoPreviewLayer como subcapa en una imagen para guardar? Quiero crear una superposición de realidad aumentada y hacer que un botón guarde la imagen en el rollo de la cámara. Al mantener presionado el botón de encendido + tecla de inicio, se captura la captura de pantalla del rollo de la cámara, lo que significa que toda la lógica de mi captura está funcionando, Y la tarea es posible. Pero parece que no puedo hacer que funcione programáticamente.

Estoy capturando una vista previa en vivo de la imagen de la cámara usando AVCaptureVideoPreviewLayer. Todos mis intentos de renderizar la imagen fallan:

previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession]; //start the session, etc... //this saves a white screen - (IBAction)saveOverlay:(id)sender { NSLog(@"saveOverlay"); UIGraphicsBeginImageContext(appDelegate.window.bounds.size); UIGraphicsBeginImageContext(scrollView.frame.size); [previewLayer.presentationLayer renderInContext:UIGraphicsGetCurrentContext()]; // [appDelegate.window.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); UIImageWriteToSavedPhotosAlbum(screenshot, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); }

// esto lo representa todo, EXCEPTO para la capa de vista previa, que está en blanco.

[appDelegate.window.layer renderInContext:UIGraphicsGetCurrentContext()];

He leído en alguna parte que esto puede deberse a problemas de seguridad del iPhone. ¿Es esto cierto?

Solo para ser claros: no quiero guardar la imagen para la cámara. Quiero guardar la capa de vista previa transparente superpuesta sobre otra imagen, creando así transparencia. Sin embargo, por alguna razón no puedo hacer que funcione.


Me gusta la sugerencia de @ Roma de usar GPU Image - una gran idea. . . . Sin embargo, si desea un enfoque puro de CocoaTouch, esto es lo que debe hacer:

Implementar AVCaptureVideoDataOutputSampleBufferDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { // Create a UIImage+Orientation from the sample buffer data if (_captureFrame) { [captureSession stopRunning]; _captureFrame = NO; UIImage *image = [ImageTools imageFromSampleBuffer:sampleBuffer]; image = [image rotate:UIImageOrientationRight]; _frameCaptured = YES; if (delegate != nil) { [delegate cameraPictureTaken:image]; } } }

Capturar como sigue:

+ (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer { // Get a CMSampleBuffer''s Core Video image buffer for the media data CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); // Lock the base address of the pixel buffer CVPixelBufferLockBaseAddress(imageBuffer, 0); // Get the number of bytes per row for the pixel buffer void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); // Get the number of bytes per row for the pixel buffer size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); // Get the pixel buffer width and height size_t width = CVPixelBufferGetWidth(imageBuffer); size_t height = CVPixelBufferGetHeight(imageBuffer); // Create a device-dependent RGB color space CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); // Create a bitmap graphics context with the sample buffer data CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); // Create a Quartz image from the pixel data in the bitmap graphics context CGImageRef quartzImage = CGBitmapContextCreateImage(context); // Unlock the pixel buffer CVPixelBufferUnlockBaseAddress(imageBuffer,0); // Free up the context and color space CGContextRelease(context); CGColorSpaceRelease(colorSpace); // Create an image object from the Quartz image UIImage *image = [UIImage imageWithCGImage:quartzImage]; // Release the Quartz image CGImageRelease(quartzImage); return (image); }

Mezcla el UIImage con la superposición

  • Ahora que tiene el UIImage, agréguelo a un nuevo UIView.
  • Añadir la superposición en la parte superior como una vista secundaria.

Captura la nueva UIView

+ (UIImage*)imageWithView:(UIView*)view { UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, [UIScreen mainScreen].scale); [view.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage* img = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return img; }


Te puedo aconsejar que pruebes GPU Image.

https://github.com/BradLarson/GPUImage

Utiliza OpenGL, por lo que es bastante rápido. Puede procesar imágenes desde la cámara y agregarles filtros (hay muchos) que incluyen detección de bordes, detección de movimiento y mucho más.

Es como OpenCV, pero basado en mi propia experiencia, la imagen de GPU es más fácil de conectar con su proyecto y el lenguaje es objetivo-c.

El problema podría aparecer si decidiste usar box2d para la física, también usa openGl y necesitarás pasar un tiempo hasta que estos 2 marcos dejen de luchar))