ios AVFoundation 点击​​聚焦

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13095007/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 20:57:45  来源:igfitidea点击:

ios AVFoundation tap to focus

ioscameraavfoundation

提问by spacecash21

I am trying to create a camera app which, would act like the default camera app more or less. The thing, which is not working for me at the moment, is tap to focus. I want the camera to focus and do whatever it does on my touched point, just like the real camera app does.

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

Here's my viewDidLoad

这是我的 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];
};

And here's the method that should make my camera focus stuff on click.

这是应该让我的相机在点击时聚焦的方法。

-(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);
    }];
}

Nothing really happens once I click on the screen.

一旦我点击屏幕,什么都不会发生。

回答by Konrad Lang

You have to adjust the touchPoint to a range of [0,1] using something like the following code:

您必须使用类似以下代码的内容将 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];

The documentation on this can be found in Apple - AV Foundation Programming Guidelines- see section Media Capturewhere you will find information on Focus Modes:

有关此方面的文档可以在Apple - AV Foundation Programming Guidelines 中找到- 请参阅媒体捕获部分,您将在其中找到有关焦点模式的信息

If it's supported, you set the focal point using focusPointOfInterest. You pass a CGPoint where {0,0} represents the top left of the picture area, and {1,1} represents the bottom right in landscape mode with the home button on the right—this applies even if the device is in portrait mode.

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

回答by Catalin

UITapGestureRecognizer *shortTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapToFocus:)];
shortTap.numberOfTapsRequired=1;
shortTap.numberOfTouchesRequired=1;
[viewCanvasRecording addGestureRecognizer:shortTap];

and then this:

然后这个:

- (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];
            }
        }
    }
}

A Swift version:

一个 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)
            }
        }
    }
}

回答by Feng Liu

So here is how I handle gestures for my AV camera preview. Setup your UITapGestureRecognizer first, then get the point by using captureDevicePointOfInterestForPoint.

所以这里是我如何处理我的 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];
  }
}

I'm using AVCaptureVideoPreviewLayer to get the touch point. But if you use GLKView to render preview instead of AVCaptureVideoPreviewLayer, you can't get the point directly but have to get the point as previous answer did.

我正在使用 AVCaptureVideoPreviewLayer 来获取接触点。但是,如果您使用 GLKView 来呈现预览而不是 AVCaptureVideoPreviewLayer,则您无法直接获得要点,而必须像以前的答案一样得到要点。

New coder to ios development. Hope this can help.

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