【问题标题】:ios AVFoundation tap to focusios AVFoundation 点击​​聚焦
【发布时间】:2012-10-26 21:59:39
【问题描述】:

我正在尝试创建一个相机应用程序,它或多或少会像默认相机应用程序一样工作。 目前对我不起作用的事情是点击聚焦。我希望相机聚焦并在我的触摸点上做任何事情,就像真正的相机应用一样。

这是我的 viewDidLoad

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Session
    _session = [[AVCaptureSession alloc] init];
    _session.sessionPreset = AVCaptureSessionPresetPhoto;

    // Input
    _videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    _videoInput = [AVCaptureDeviceInput deviceInputWithDevice:_videoDevice error:nil];

    // Output
    _frameOutput = [[AVCaptureVideoDataOutput alloc] init];
    _frameOutput.videoSettings = [NSDictionary dictionaryWithObject:AVVideoCodecJPEG forKey:AVVideoCodecKey];

    [_frameOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
    [_session addInput:_videoInput];
    [_session addOutput:_frameOutput];
    [_session startRunning];
};

这是让我的相机在点击时对焦的方法。

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    [touches enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
        UITouch *touch = obj;
        CGPoint touchPoint = [touch locationInView:touch.view];
        focusLayer.frame = CGRectMake((touchPoint.x-25), (touchPoint.y-25), 50, 50);

        if ([_videoDevice isFocusPointOfInterestSupported]) {
            NSError *error;
            if ([_videoDevice lockForConfiguration:&error]) {
                [_videoDevice setFocusPointOfInterest:touchPoint];
                [_videoDevice setExposurePointOfInterest:touchPoint];

                [_videoDevice setFocusMode:AVCaptureFocusModeAutoFocus];
                if ([_videoDevice isExposureModeSupported:AVCaptureExposureModeAutoExpose]){
                    [_videoDevice setExposureMode:AVCaptureExposureModeAutoExpose];
                }
                [_videoDevice unlockForConfiguration];
            }
        }


        // NSLog(@"x = %f, y = %f", touchPoint.x, touchPoint.y);
    }];
}

点击屏幕后什么都没有发生。

【问题讨论】:

    标签: ios camera avfoundation


    【解决方案1】:

    您必须使用以下代码将 touchPoint 调整为 [0,1] 的范围:

        CGRect screenRect = [[UIScreen mainScreen] bounds];
        screenWidth = screenRect.size.width;
        screenHeight = screenRect.size.height;  
        double focus_x = thisFocusPoint.center.x/screenWidth;
        double focus_y = thisFocusPoint.center.y/screenHeight;
    
        [[self captureManager].videoDevice lockForConfiguration:&error];
        [[self captureManager].videoDevice setFocusPointOfInterest:CGPointMake(focus_x,focus_y)];
        [[self captureManager].videoDevice unlockForConfiguration];
    

    这方面的文档可以在Apple - AV Foundation Programming Guidelines - see section Media Capture where you will find information on Focus Modes找到:

    如果支持,您可以使用 focusPointOfInterest 设置焦点。您传递一个 CGPoint,其中 {0,0} 代表图片区域的左上角,{1,1} 代表横向模式下的右下角,主页按钮位于右侧——即使设备处于纵向模式也适用.

    【讨论】:

    • 是否有文档或其他内容可以解释为什么需要这样做?
    • 将答案更新为指向 Apple 提供的文档。
    • 你也可以使用AVCaptureVideoPreviewLayercaptureDevicePointOfInterestForPoint 方法来计算焦点。
    • @KonradLang 我知道我迟到了,但这里的thisFocusPoint 是什么?
    【解决方案2】:
    UITapGestureRecognizer *shortTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapToFocus:)];
    shortTap.numberOfTapsRequired=1;
    shortTap.numberOfTouchesRequired=1;
    [viewCanvasRecording addGestureRecognizer:shortTap];
    

    然后是这个:

    - (void)handleTapToFocus:(UITapGestureRecognizer *)tapGesture
    {
        AVCaptureDevice *acd=!currentFrontCamera ? captureBackInput.device : captureFrontInput.device;
    
        if (tapGesture.state == UIGestureRecognizerStateEnded)
        {
            CGPoint thisFocusPoint = [tapGesture locationInView:viewCanvasRecording];
    
            double focus_x = thisFocusPoint.x/viewCanvasRecording.frame.size.width;
            double focus_y = thisFocusPoint.y/viewCanvasRecording.frame.size.height;
    
            if ([acd isFocusModeSupported:AVCaptureFocusModeAutoFocus] && [acd isFocusPointOfInterestSupported])
            {
                if ([acd lockForConfiguration:nil])
                {
                    [acd setFocusMode:AVCaptureFocusModeAutoFocus];
                    [acd setFocusPointOfInterest:CGPointMake(focus_x, focus_y)];
    
                    /*
                    if ([acd isExposureModeSupported:AVCaptureExposureModeAutoExpose] && [acd isExposurePointOfInterestSupported])
                    {
                        [acd setExposureMode:AVCaptureExposureModeAutoExpose];
                        [acd setExposurePointOfInterest:CGPointMake(focus_x, focus_y)];
                    }*/
    
                    [acd unlockForConfiguration];
                }
            }
        }
    }
    

    Swift 版本:

    @IBAction func tapToFocus(_ sender: UITapGestureRecognizer) {
        if (sender.state == .ended) {
            let thisFocusPoint = sender.location(in: previewView)
    
            print("touch to focus ", thisFocusPoint)
    
            let focus_x = thisFocusPoint.x / previewView.frame.size.width
            let focus_y = thisFocusPoint.y / previewView.frame.size.height
    
            if (captureDevice!.isFocusModeSupported(.autoFocus) && captureDevice!.isFocusPointOfInterestSupported) {
                do {
                    try captureDevice?.lockForConfiguration()
                    captureDevice?.focusMode = .autoFocus
                    captureDevice?.focusPointOfInterest = CGPoint(x: focus_x, y: focus_y)
    
                    if (captureDevice!.isExposureModeSupported(.autoExpose) && captureDevice!.isExposurePointOfInterestSupported) {
                        captureDevice?.exposureMode = .autoExpose;
                        captureDevice?.exposurePointOfInterest = CGPoint(x: focus_x, y: focus_y);
                     }
    
                    captureDevice?.unlockForConfiguration()
                } catch {
                    print(error)
                }
            }
        }
    }
    

    【讨论】:

    • 对于focus_xfocus_y 为什么要除以widthheight
    • 啊,请从 Apple 文档中阅读:此外,设备可能支持兴趣焦点。您使用 focusPointOfInterestSupported 测试支持。如果支持,您可以使用 focusPointOfInterest 设置焦点。您传递一个 CGPoint,其中 {0,0} 代表图片区域的左上角,{1,1} 代表横向模式下的右下角,主页按钮在右侧——即使设备处于纵向模式也适用.
    • 顺便说一句,viewCanvasRecording 是什么?
    【解决方案3】:

    以下是我为 AV 摄像机预览处理手势的方法。首先设置您的 UITapGestureRecognizer,然后使用 captureDevicePointOfInterestForPoint 获取点。

    - (void)setupGestures
    {
      UITapGestureRecognizer *tapToFocusRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
                                              action:@selector(handleTapToFocusAndExposureRecognizer:)];
      [self addGestureRecognizer:tapToFocusRecognizer];
    }
    
    - (void)handleTapToFocusAndExposureRecognizer:(UITapGestureRecognizer*)tabRecognizer {
      CGPoint touchPoint = [tabRecognizer locationInView:self];
      CGPoint point = [self.previewLayer captureDevicePointOfInterestForPoint:touchPoint];
      AVCaptureDevice *device = [self.videoCaptureDeviceInput device];
      NSError *error = nil;
    
      if (tabRecognizer.state == UIGestureRecognizerStateEnded) {
        if (![device lockForConfiguration:&error]) {
          if (error) {
            RCTLogError(@"%s: %@", __func__, error);
          }
          return;
        }
    
        [device setFocusPointOfInterest:CGPointMake(point.x, point.y)];
        [device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
    
        [device setExposurePointOfInterest:CGPointMake(point.x, point.y)];
        [device setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
    
        [device unlockForConfiguration];
      }
    }
    

    我正在使用 AVCaptureVideoPreviewLayer 来获取接触点。但是如果你使用 GLKView 来渲染预览而不是 AVCaptureVideoPreviewLayer,你不能直接得到要点,而必须像之前的答案那样得到要点。

    ios 开发的新编码器。希望这能有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-27
      • 1970-01-01
      • 2011-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多