有没有办法获得相机流的iOS上的亮度级别?

时间:2012-12-04 17:38:53

标签: objective-c ios camera

我正在使用iPhone / iPad相机获取视频流并对流进行识别,但随着光照的变化,它会对稳健性产生负面影响。我已经在不同的灯光下测试了不同的设置并且可以使它工作,但是我需要尝试在运行时调整设置。

我可以计算每帧的简单亮度检查,但相机会调整并抛出我的结果。我可以观察到急剧变化并运行检查,但渐进的变化也会使我的结果失效。

理想情况下,我想要访问流的相机/ EXIF数据并查看注册未过滤亮度的内容,有没有办法做到这一点?

(我正在为iOS 5及更高版本的设备工作)

谢谢

2 个答案:

答案 0 :(得分:8)

适用于iOS 4.0及更高版本。可以从CMSampleBufferRef获取EXIF信息。

//Import ImageIO & include framework in your project. 
#import <ImageIO/CGImageProperties.h>

在您的示例缓冲区委托免费桥接将获得CoreMedia的CMGetAttachment的NSDictionary结果。

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
    NSDictionary* dict = (NSDictionary*)CMGetAttachment(sampleBuffer, kCGImagePropertyExifDictionary, NULL);

答案 1 :(得分:1)

完整代码,在我自己的应用中使用:

- (void)setupAVCapture {

//-- Setup Capture Session.
_session = [[AVCaptureSession alloc] init];
[_session beginConfiguration];

//-- Set preset session size.
[_session setSessionPreset:AVCaptureSessionPreset1920x1080];

//-- Creata a video device and input from that Device.  Add the input to the capture session.
AVCaptureDevice * videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if(videoDevice == nil)
    assert(0);

//-- Add the device to the session.
NSError *error;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];
if(error)
    assert(0);

[_session addInput:input];

//-- Create the output for the capture session.
AVCaptureVideoDataOutput * dataOutput = [[AVCaptureVideoDataOutput alloc] init];
[dataOutput setAlwaysDiscardsLateVideoFrames:YES]; // Probably want to set this to NO when recording

//-- Set to YUV420.
[dataOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange]
                                                         forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; // Necessary for manual preview

// Set dispatch to be on the main thread so OpenGL can do things with the data
[dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];

[_session addOutput:dataOutput];
[_session commitConfiguration];

[_session startRunning];
}

- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
       fromConnection:(AVCaptureConnection *)connection
{
    CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL,
                                                                 sampleBuffer, kCMAttachmentMode_ShouldPropagate);
    NSDictionary *metadata = [[NSMutableDictionary alloc]
                              initWithDictionary:(__bridge NSDictionary*)metadataDict];
    CFRelease(metadataDict);
    NSDictionary *exifMetadata = [[metadata
                                   objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy];
    self.autoBrightness = [[exifMetadata
                         objectForKey:(NSString *)kCGImagePropertyExifBrightnessValue] floatValue];

    float oldMin = -4.639957; // dark
    float oldMax = 4.639957; // light
    if (self.autoBrightness > oldMax) oldMax = self.autoBrightness; // adjust oldMax if brighter than expected oldMax

    self.lumaThreshold = ((self.autoBrightness - oldMin) * ((3.0 - 1.0) / (oldMax - oldMin))) + 1.0;

    NSLog(@"brightnessValue %f", self.autoBrightness);
    NSLog(@"lumaThreshold %f", self.lumaThreshold);
}

lumaThreshold变量作为一个统一变量发送到我的片段着色器,它将Y采样器纹理相乘,以根据环境的亮度找到理想的亮度。现在,它使用后置摄像头;我可能会切换到前置摄像头,因为我只是改变了亮度&#34;用于调整室内/室外观看的屏幕,用户的眼睛位于摄像机的正面(而不是背面)。