web-dev-qa-db-fra.com

ios AVFoundation tapez pour se concentrer

J'essaie de créer une application de caméra qui agirait plus ou moins comme l'application de caméra par défaut. Ce qui ne fonctionne pas pour moi pour l'instant, c'est de mettre le doigt sur la mise au point. Je veux que l'appareil photo se concentre et fasse tout ce qu'il fait sur mon point touché, comme le fait la vraie application pour appareil photo.

Voici mon 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];
};

Et voici la méthode qui devrait faire que mon appareil photo se concentre sur le clic.

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

Rien ne se passe vraiment une fois que je clique sur l'écran.

23
spacecash21

Vous devez ajuster le touchPoint sur une plage de [0,1] en utilisant quelque chose comme le code suivant:

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

La documentation à ce sujet se trouve dans Instructions de programmation Apple - AV Foundation - voir la section Capture de média où vous trouverez des informations sur Modes de mise au point :

S'il est pris en charge, vous définissez le point focal à l'aide de focusPointOfInterest. Vous passez un point CGPoint où {0,0} représente le coin supérieur gauche de la zone d'image et {1,1} le coin inférieur droit en mode paysage avec le bouton d'accueil situé à droite (cela s'applique même si l'appareil est en mode portrait). .

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

et puis ceci: 

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

Une 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)
            }
        }
    }
}
6
Catalin

Alors voici comment je gère les gestes pour mon aperçu de la caméra AV. Configurez d'abord votre UITapGestureRecognizer, puis obtenez le point en utilisant 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];
  }
}

J'utilise AVCaptureVideoPreviewLayer pour obtenir le point de contact. Mais si vous utilisez GLKView pour rendre l'aperçu au lieu d'AVCaptureVideoPreviewLayer, vous ne pouvez pas obtenir le point directement, mais vous devez le faire comme le faisait la réponse précédente.

Nouveau codeur pour le développement iOS. J'espère que cela peut aider. 

1
Feng Liu