2012-01-26 15 views
18

To wydaje się proste, ale doprowadza mnie do szału. Czy można przekonwertować UIView zawierający AVCaptureVideoPreviewLayer jako podwarstwie na obraz do zapisania? Chcę utworzyć nakładkę rozszerzonej rzeczywistości i mieć przycisk zapisać obraz do rolki aparatu. Przytrzymanie przycisku zasilania + klawisza domowego powoduje przechwycenie zrzutu ekranu na rolce aparatu, co oznacza, że ​​działa cała moja logika przechwytywania, ORAZ zadanie jest możliwe. Ale nie mogę sprawić, żeby program działał programowo.Czy można renderować AVCaptureVideoPreviewLayer w kontekście graficznym?

Przechwytywam bieżący podgląd obrazu z kamery przy użyciu AVCaptureVideoPreviewLayer. Wszystkie moje próby renderowania obrazu kończą się niepowodzeniem:

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

// To powoduje, że wszystko, Z WYJĄTKIEM dla warstwy podglądu, która jest pusta.

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

Czytałem gdzieś, że może to być spowodowane problemami bezpieczeństwa iPhone'a. Czy to prawda?

Dla jasności: Nie chcę zapisywać obrazu dla kamery. Chcę zapisać przezroczystą warstwę podglądu nałożoną na inny obraz, tworząc w ten sposób przezroczystość. Jednak z jakiegoś powodu nie mogę sprawić, żeby działało.

Odpowiedz

4

Mogę doradzić, aby wypróbować obraz GPU.

https://github.com/BradLarson/GPUImage

Wykorzystuje OpenGL, więc jest to dość szybko. Może przetwarzać obrazy z kamery i dodawać do nich filtry (jest ich dużo), w tym wykrywanie krawędzi, wykrywanie ruchu i znacznie więcej. To jest jak OpenCV, ale na podstawie własnego doświadczenia obraz GPU jest łatwiejszy do połączenia z twoim projektem a język jest obiektywny-c.

Problem może pojawić się, jeśli postanowił wykorzystać box2d fizyki - to wykorzystuje OpenGL zbyt i trzeba będzie spędził jakiś czas po dziś 2 ram zatrzyma walki))

+0

Chyba co PO i próbują, jest uzyskanie paszy na żywo wideo za pomocą avcapturevideopreviewlayer i próbują dodać skalowany obraz. Próbuję dodać skalowany obraz do strumienia wideo na żywo w oparciu o wykrywanie twarzy, a zapisany zrzut ekranu jest tylko obrazem nakładki, a nie avcapturevideopreviewlayer. –

+0

Na grafice GPU już dodałem filtry na warstwach, więc jestem prawie pewien, że istnieje sposób na zapisanie tylko bieżącej warstwy (w obrazie GPU jest metoda na wykonanie UIImage z ramki) Jeśli chcesz uzyskać dokładnie to, co jest na wyświetlaczu - tam jest sposobem na robienie zrzutów ekranu programowo. Nie pamiętam go teraz, ale widziałem go na stackoverflow) – Roma

+0

Roma, dziękuję bardzo za odpowiedź. Chociaż nie korzystałem z GPUImage, na pewno wkrótce go użyję. Dzięki za umieszczenie go jako alternatywnej opcji. –

15

lubię @ sugestią Roma wykorzystania GPU obraz - świetny pomysł. . . . Jednak jeśli chcesz podejście czysto Cocoa Touch, oto co należy zrobić:

Wdrożenie 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]; 
     } 
    } 
} 

uchwycić jak następuje:

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

Wymieszać UIImage z nakładką

  • Teraz, gdy masz UIImage, dodaj go do nowego UIView.
  • Dodaj nakładkę na wierzch jako pod-widok.

Przechwytywanie nowy 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

Myślę, że tego właśnie szukam. Postaram się uruchomić i poinformować, jak to działa. Dzięki za szybką odpowiedź! –

+0

używasz rozszerzenia uiimage dla image = [image rotate: UIImageOrientationRight]; ? –

+0

Tak, ten krok jest opcjonalny. Pozwól, że dam ci kod. –

Powiązane problemy