首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >iOS + AVFoundation。使用相同的手动曝光设置,照片亮度不同

iOS + AVFoundation。使用相同的手动曝光设置,照片亮度不同
EN

Stack Overflow用户
提问于 2015-12-29 20:49:25
回答 2查看 3.4K关注 0票数 3

我用AVFoundation拍照。问题是,即使不断设置曝光时间,ISO和白平衡,我也能得到不同亮度的照片。手电筒、闪光灯和所有可能的稳定器都被禁用。

这个问题也出现在介绍使用摄像头的标准苹果应用程序中:https://developer.apple.com/library/ios/samplecode/AVCam/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010112

这是我通过这个应用程序拍摄的视频,除了在会话初始化期间设置手动曝光之外,没有任何更改:

https://www.youtube.com/watch?v=g9NOWGVeftI

请注意,如果数码相机的曝光设置是恒定的,则突然变亮是不应该的(不,当设置了曝光设置并调用了完成处理程序时,这不是瞬间;设置已经设置)。

变亮并不总是发生,但无论如何,如果我将相机移开并重新瞄准对象,可能会有显着的亮度差异。但是如果我在没有移动相机的情况下拍摄一系列的照片,亮度是一样的。

(当然,object的照片是在相同的光线环境下拍摄的)

可能这种增亮是设置自定义曝光设置的一部分(因为它通常在一开始发生),而它的后期激活是我应该加快速度的过程,但我不知道怎么做。

我在iPod Touch5和iPad Air上有这个效果。我想这也可以发生在其他iOS设备上。

场景亮度似乎会影响最终图像的亮度(也会影响预览层的亮度)。设备不只是设置给定的曝光设置;它会根据当前场景亮度添加一些校正,并在可见场景的常见亮度发生较大变化时更改此校正。

如果我用手关闭相机,将手移开并拍照,它可以比之前没有关闭相机而拍摄的相机更亮。

可能不仅仅是亮度,还有对比度,因为当我将摄像头从白色显示屏上移开时,屏幕外相对较暗的物体变得可见时,可能会变亮。

曝光目标偏移量在增亮前略小于零,增亮后略大于零。

我假设这个值是基于这个意外调整的参数(就像在自动曝光模式中一样)。

但是通过观察目标偏移量的变化和设置相等的曝光目标偏移量来防止它的尝试失败了,因为目标偏移量一直在变化,而且不可能让工作相机永久地改变它的目标偏移量。

通过设置曝光目标偏置使曝光目标偏移值在捕获前远离零来强制调整的尝试也失败了,因为什么都没有发生,并且我可以在尝试补偿之后进行增亮。即使在自定义模式下,目标偏置也会影响客户可见的曝光偏移量,但它似乎不会影响负责曝光的部件中的设备行为。

我还发现在锁定曝光模式下没有亮度跳跃(或者我错过了…)。。我试图在设置自定义曝光值后设置此模式,但问题是,在锁定模式下,设备不仅会修复当前的曝光值,还会进行初始调整,从而更改曝光设置。

跳转后,我从exif数据和AVCaptureDevice实例中获取的曝光值没有变化。我试着通过KVO观察曝光值,但没有任何可疑之处。当我设置自定义模式时,曝光持续时间和ISO被更改了几次,然后调用完成处理程序。变亮的时间可以推迟,但不会影响我可以获得的当前曝光值。

所有这一切都令人困惑。如何提供图像亮度和曝光设置之间的直接关系?

EN

回答 2

Stack Overflow用户

发布于 2016-05-14 13:01:08

代码语言:javascript
运行
复制
- (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采样器纹理相乘,以根据环境的亮度找到理想的亮度。现在,它使用后置摄像头;我可能会切换到前置摄像头,因为我只是改变屏幕的“亮度”来调整以适应室内/室外观看,而用户的眼睛在摄像头的前部(而不是后部)。

票数 1
EN

Stack Overflow用户

发布于 2019-04-25 07:27:30

在修修补补之后,我想出了如何轻松锁定你的曝光率。在主摄像机初始化期间,添加:

代码语言:javascript
运行
复制
device.exposureMode = AVCaptureDevice.ExposureMode.custom

一旦设备被锁定以进行配置

和(非常重要)

代码语言:javascript
运行
复制
device.exposureMode = AVCaptureDevice.ExposureMode.locked

这两者都可以确保:

  1. 您可以使用您的自定义设置来初始化摄像机
  2. 在进行更改后,摄像机将保持完全锁定状态

你的相机初始化代码应该如下所示:

代码语言:javascript
运行
复制
 try device.lockForConfiguration()  
          device.exposureMode = AVCaptureDevice.ExposureMode.custom 
          device.setExposureModeCustom(duration: durationCust, iso: minISO, completionHandler: nil)
          device.setWhiteBalanceModeLocked(with: deviceGains) {
                    (timestamp:CMTime) -> Void in
            }
          device.exposureMode = AVCaptureDevice.ExposureMode.locked
            device.unlockForConfiguration()

当您想要主动更改曝光参数时,请不要在实际更改曝光之外将曝光重新声明为锁定或自定义。函数中的代码应该如下所示:

代码语言:javascript
运行
复制
try device.lockForConfiguration()
                 device.setExposureModeCustom(duration: durationCust, iso: minISO, completionHandler: nil)
             device.unlockForConfiguration()

我很高兴能弄清楚这一点-我希望有人能发现它是有帮助的:)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34511431

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档