2012-01-19 9 views
41

Tôi đang chụp ảnh sử dụng mã nàyios chụp ảnh sử dụng AVFramework

#pragma mark - image capture 

// Create and configure a capture session and start it running 
- (void)setupCaptureSession 
{ 
    NSError *error = nil; 

    // Create the session 
    AVCaptureSession *session = [[AVCaptureSession alloc] init]; 

    // Configure the session to produce lower resolution video frames, if your 
    // processing algorithm can cope. We'll specify medium quality for the 
    // chosen device. 
    session.sessionPreset = AVCaptureSessionPresetMedium; 

    // Find a suitable AVCaptureDevice 
    AVCaptureDevice *device = [AVCaptureDevice 
          defaultDeviceWithMediaType:AVMediaTypeVideo]; 

    // Create a device input with the device and add it to the session. 
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device 
                    error:&error]; 
    if (!input) 
    { 
     NSLog(@"PANIC: no media input"); 
    } 
    [session addInput:input]; 

    // Create a VideoDataOutput and add it to the session 
    AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init]; 
    [session addOutput:output]; 

    // Configure your output. 
    dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL); 
    [output setSampleBufferDelegate:self queue:queue]; 
    dispatch_release(queue); 

    // Specify the pixel format 
    output.videoSettings = 
    [NSDictionary dictionaryWithObject: 
    [NSNumber numberWithInt:kCVPixelFormatType_32BGRA] 
          forKey:(id)kCVPixelBufferPixelFormatTypeKey]; 


    // If you wish to cap the frame rate to a known value, such as 15 fps, set 
    // minFrameDuration. 

    // Start the session running to start the flow of data 
    [session startRunning]; 

    // Assign session to an ivar. 
    [self setSession:session]; 
} 




// Delegate routine that is called when a sample buffer was written 
- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
    fromConnection:(AVCaptureConnection *)connection 
{ 
    NSLog(@"captureOutput: didOutputSampleBufferFromConnection"); 

    // Create a UIImage from the sample buffer data 
    UIImage *image = [self imageFromSampleBuffer:sampleBuffer]; 

    //< Add your code here that uses the image > 
    [self.imageView setImage:image]; 
    [self.view setNeedsDisplay]; 
} 


// Create a UIImage from sample buffer data 
- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer 
{ 
    NSLog(@"imageFromSampleBuffer: called"); 
    // 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); 
} 

-(void)setSession:(AVCaptureSession *)session 
{ 
    NSLog(@"setting session..."); 
    self.captureSession=session; 
} 

Chụp đang hoạt động. Nhưng! Tôi cần thay đổi thành mọi thứ: - luồng video từ máy ảnh trong chế độ xem của tôi. - nhận ảnh mỗi (ví dụ 5 giây) từ ảnh đó. Hãy giúp tôi, làm thế nào nó có thể được thực hiện?

+13

+1 để chia sẻ mã chi tiết. Giúp đỡ rất nhiều trong công việc của tôi – zolio

Trả lời

18

Thêm dòng sau

output.minFrameDuration = CMTimeMake(5, 1); 

dưới comment

// If you wish to cap the frame rate to a known value, such as 15 fps, set 
// minFrameDuration. 

nhưng trên

[session startRunning]; 

Sửa

Sử dụng mã sau đây để xem trước đầu ra của máy ảnh.

AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session]; 
UIView *aView = self.view; 
CGRect videoRect = CGRectMake(0.0, 0.0, 320.0, 150.0); 
previewLayer.frame = videoRect; // Assume you want the preview layer to fill the view. 
[aView.layer addSublayer:previewLayer]; 

Chỉnh sửa 2: tốt Ok ..

Apple đã cung cấp một cách để thiết lập các minFrameDuration here

Vì vậy, bây giờ, sử dụng đoạn mã sau để thiết lập độ dài khung

AVCaptureConnection *conn = [output connectionWithMediaType:AVMediaTypeVideo]; 

if (conn.supportsVideoMinFrameDuration) 
    conn.videoMinFrameDuration = CMTimeMake(5,1); 
if (conn.supportsVideoMaxFrameDuration) 
    conn.videoMaxFrameDuration = CMTimeMake(5,1); 
+0

Cảm ơn. Làm cách nào để đặt luồng video phát từ máy ảnh trong chế độ xem của tôi? Tôi có nên thêm AVCaptureOutput khác không? – Oleg

+0

và bằng cách này, phương pháp này không được dùng nữa – Oleg

+2

Sử dụng 'AVCaptureVideoPreviewLayer' để phát bản xem trước. Xem câu trả lời cập nhật của tôi. – Ilanchezhian

15

Hãy cẩn thận - gọi lại từ AVCaptureOutput được đăng trong hàng đợi công văn yo bạn đã chỉ định. Tôi thấy bạn thực hiện cập nhật giao diện người dùng từ cuộc gọi lại này và điều đó là sai. Bạn chỉ nên thực hiện chúng trong hàng đợi chính. Ví dụ.

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
    didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection 
{ 
    NSLog(@"captureOutput: didOutputSampleBufferFromConnection"); 
    // Create a UIImage from the sample buffer data 
    UIImage *image = [self imageFromSampleBuffer:sampleBuffer]; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
    //< Add your code here that uses the image > 
     [self.imageView setImage:image]; 
     [self.view setNeedsDisplay]; 
    } 
} 
+1

Bạn là người tiết kiệm cuộc sống! Điều này đã khiến tôi không thể cập nhật hình ảnh từ máy ảnh, cảm ơn! –

+0

Tuyệt vời! Cảm ơn! –

4

Và đây là một phiên bản Swift chức năng imageFromSampleBuffer:

func imageFromSampleBuffer(sampleBuffer:CMSampleBuffer!) -> UIImage { 
    let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)! 
    CVPixelBufferLockBaseAddress(imageBuffer, 0) 

    let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer) 
    let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer) 
    let width = CVPixelBufferGetWidth(imageBuffer) 
    let height = CVPixelBufferGetHeight(imageBuffer) 

    let colorSpace = CGColorSpaceCreateDeviceRGB() 

    let bitmapInfo:CGBitmapInfo = [.ByteOrder32Little, CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedFirst.rawValue)] 
    let context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, bitmapInfo.rawValue) 

    let quartzImage = CGBitmapContextCreateImage(context) 
    CVPixelBufferUnlockBaseAddress(imageBuffer, 0) 

    let image = UIImage(CGImage: quartzImage!) 
    return image 
} 

Trên làm việc cho tôi với sau cài đặt video:

videoDataOutput = AVCaptureVideoDataOutput() 
videoDataOutput?.videoSettings = [kCVPixelBufferPixelFormatTypeKey:Int(kCVPixelFormatType_32BGRA)] 
      videoDataOutput?.setSampleBufferDelegate(self, queue: queue) 
+0

cảm ơn! điều này đã cứu tôi rất nhiều thời gian – stanley