2016-12-01 9 views
-1

В osx я использую AVFoundation для захвата изображения с USB-камеры, все работает нормально, но изображение, которое я получаю, темнее по сравнению с живым видео.AVFoundation image capture is dark

конфигурации устройства захвата

-(BOOL)prepareCapture{ 
captureSession = [[AVCaptureSession alloc] init]; 
NSError *error; 

imageOutput=[[AVCaptureStillImageOutput alloc] init]; 
NSNumber * pixelFormat = [NSNumber numberWithInt:k32BGRAPixelFormat]; 
[imageOutput setOutputSettings:[NSDictionary dictionaryWithObject:pixelFormat forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; 

videoOutput=[[AVCaptureMovieFileOutput alloc] init]; 

AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:MyVideoDevice error:&error]; 
if (videoInput) { 
    [captureSession beginConfiguration]; 
    [captureSession addInput:videoInput]; 
    [captureSession setSessionPreset:AVCaptureSessionPresetHigh]; 
    //[captureSession setSessionPreset:AVCaptureSessionPresetPhoto]; 
    [captureSession addOutput:imageOutput]; 
    [captureSession addOutput:videoOutput]; 
    [captureSession commitConfiguration]; 
} 
else { 
    // Handle the failure. 
    return NO; 
} 
return YES; 
} 

Добавить вид для предварительного просмотра

-(void)settingPreview:(NSView*)View{ 
// Attach preview to session 
previewView = View; 
CALayer *previewViewLayer = [previewView layer]; 
[previewViewLayer setBackgroundColor:CGColorGetConstantColor(kCGColorBlack)]; 
AVCaptureVideoPreviewLayer *newPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:captureSession]; 
[newPreviewLayer setFrame:[previewViewLayer bounds]]; 
[newPreviewLayer setAutoresizingMask:kCALayerWidthSizable | kCALayerHeightSizable]; 
[previewViewLayer addSublayer:newPreviewLayer]; 
//[self setPreviewLayer:newPreviewLayer]; 
[captureSession startRunning]; 
} 

код для захвата изображения

-(void)captureImage{ 
AVCaptureConnection *videoConnection = nil; 
for (AVCaptureConnection *connection in imageOutput.connections) { 
    for (AVCaptureInputPort *port in [connection inputPorts]) { 
     if ([[port mediaType] isEqual:AVMediaTypeVideo]) { 
      videoConnection = connection; 
      break; 
     } 
    } 
    if (videoConnection) { break; } 
} 
[imageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: 
^(CMSampleBufferRef imageSampleBuffer, NSError *error) { 
    CFDictionaryRef exifAttachments = 
    CMGetAttachment(imageSampleBuffer, kCGImagePropertyExifDictionary, NULL); 
    if (exifAttachments) { 
     // Do something with the attachments. 
    } 
    // Continue as appropriate. 
    //IMG is a global NSImage 
    IMG = [self imageFromSampleBuffer:imageSampleBuffer]; 
    [[self delegate] imageReady:IMG]; 
}]; 
} 

Создать NSImage из буфера данных образцов, я думаю, проблема здесь

- (NSImage *) 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]; 
NSImage * image = [[NSImage alloc] initWithCGImage:quartzImage size:NSZeroSize]; 
// Release the Quartz image 
CGImageRelease(quartzImage); 

return (image); 
} 
+0

у меня нет увидеть что-нибудь, торчащее в быстром просмотре кода ... но один причина, по которой изображения AVCapture могут быть темными, заключается в том, что камера занимает немного времени, чтобы автоматически адаптировать фокус, экспозицию и т. д. Возможно, вы вызываете свой метод 'captureImage' сразу после вашего метода' setPreview', который запускает сеанс захвата? – rickster

+0

Код копируется в основном из примеров Apple. ** установкаПросмотр ** вызывается при запуске программы. Дело в том, что сохраненное изображение немного более темное, разница с живым невелика, как будто я немного уменьшаю яркость. Я думаю, что проблема возникает при преобразовании из ** CMSampleBufferRef ** в ** NSImage ** – Mex

ответ

0

Решение найдено

Проблема была в imageFromSampleBuffer Я использовал этот код и картинка идеально

// Continue as appropriate. 
    //IMG = [self imageFromSampleBuffer:imageSampleBuffer]; 

    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(imageSampleBuffer); 

    if (imageBuffer) { 
     CVBufferRetain(imageBuffer); 

     NSCIImageRep* imageRep = [NSCIImageRep imageRepWithCIImage: [CIImage imageWithCVImageBuffer: imageBuffer]]; 

     IMG = [[NSImage alloc] initWithSize: [imageRep size]]; 
     [IMG addRepresentation: imageRep]; 

     CVBufferRelease(imageBuffer); 
    } 

код найден в этом answer