2012-01-26 2 views
18

Это похоже на простую задачу, но она меня заводит. Возможно ли преобразовать UIView, содержащий AVCaptureVideoPreviewLayer, в качестве подслоя в изображение, которое нужно сохранить? Я хочу создать обложку дополненной реальности и нажать кнопку, чтобы сохранить изображение в рулоне камеры. Удерживание кнопки питания + домашняя клавиша захватывает скриншот на рулон камеры, что означает, что вся моя логика захвата работает, И эта задача возможна. Но я, похоже, не могу заставить его работать программно.Можно ли визуализировать AVCaptureVideoPreviewLayer в графическом контексте?

Я собираю предварительный просмотр изображения камеры с помощью AVCaptureVideoPreviewLayer. Все мои попытки вынести изображение не в состоянии:

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); 
} 

// это делает все, КРОМЕ для предварительного просмотра слоя, который является пустым.

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

Я где-то читал, что это может быть связано с проблемами безопасности iPhone. Это правда?

Для большей ясности: Я не хочу сохранять изображение для камеры. Я хочу сохранить прозрачный слой предварительного просмотра поверх другого изображения, создавая прозрачность. По какой-то причине я не могу заставить его работать.

ответ

4

Я могу посоветовать вам попробовать изображение GPU.

https://github.com/BradLarson/GPUImage

Он использует OpenGL, так что это довольно быстро. Он может обрабатывать снимки с камеры и добавлять к ним фильтры (их много), включая обнаружение кромок, обнаружение движения и многое другое

Это как OpenCV, но на основе моего собственного опыта. Графический образ легче подключиться к вашему проекту. и язык объективен. c.

Проблема может появиться, если вы решили использовать box2d физики - это использует OpenGL и вы тоже нужно будет потрачено некоторое время до этого 2 рамок прекратит боевые действия))

+0

Я думаю, что ОП и я пытаюсь, чтобы получить видеопоток с помощью avcapturevideopreviewlayer и пытаются добавить масштабируется изображение. Я пытаюсь добавить масштабированное изображение поверх живого видеопотока на основе распознавания лиц, а сохраненный снимок - это только оверлей, а не avcapturevideopreviewlayer. –

+0

В графическом графическом изображении там добавляются фильтры на слоях, поэтому я уверен, что есть способ сохранить только текущий слой (есть метод в графическом изображении, чтобы сделать UIImage из кадра). Если вы хотите получить только то, что находится на дисплее, - там это способ сделать скриншот программным.Я не могу вспомнить его сейчас, но я видел его на stackoverflow) – Roma

+0

Рома, большое спасибо за ваш ответ. Хотя я не использовал GPUImage, я, конечно, буду использовать его в ближайшее время. Спасибо, что разместили его в качестве альтернативного варианта. –

15

мне нравится @ предложение Ромы использования GPU Image - отличная идея. , , , Однако, если вы хотите чистый CocoaTouch подход, вот что нужно сделать:

Реализовать 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]; 
     } 
    } 
} 

Захват следующим образом:

+ (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); 
} 

Смешать UIImage с наложением

  • Теперь, когда у вас есть UIImage, добавьте его в новый UIView.
  • Добавить наложение сверху в качестве подзадачи.

Capture новый UIView

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

Я думаю, что это то, что я ищу. Попробуем это запустить и сообщить, как это происходит. Спасибо за быстрый ответ! –

+0

Вы используете расширение uiimage для изображения = [поворот изображения: UIImageOrientationRight]; ? –

+0

Да, этот шаг является необязательным. Однако позвольте мне дать вам код. –

Смежные вопросы