2012-10-26 14 views
22

Sto provando a creare un'applicazione per la fotocamera che, si comporterebbe più o meno come l'app fotocamera predefinita. La cosa, che al momento non funziona per me, è toccare per mettere a fuoco. Voglio che la fotocamera si concentri e faccia qualsiasi cosa sul mio punto toccato, proprio come fa l'app della fotocamera reale.ios AVFoundation toccare per mettere a fuoco

Ecco la mia 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]; 
}; 

Ed ecco il metodo che dovrebbe rendere la mia roba messa a fuoco al 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); 
    }]; 
} 

Nulla accade realmente quando faccio clic sullo schermo.

risposta

31

è necessario regolare il TouchPoint a una serie di [0,1] usando qualcosa come il seguente codice:

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 documentazione su questo può essere trovato in Apple - AV Foundation Programming Guidelines - see section Media Capture where you will find information on Focus Modes:

Se è supportato, si imposta il punto focale utilizzando focusPointOfInterest. Si passa un CGPoint dove {0,0} rappresenta la parte in alto a sinistra dell'area dell'immagine e {1,1} rappresenta la parte in basso a destra in modalità orizzontale con il pulsante home sulla destra: questo si applica anche se il dispositivo è in modalità verticale .

+0

Esiste una documentazione o qualcosa che spiega il motivo per cui questo deve essere fatto in questo modo? – spacecash21

+0

Aggiornato la risposta per indicare la documentazione fornita da Apple. –

+19

È anche possibile utilizzare 'AVCaptureVideoPreviewLayer' ed è il metodo' captureDevicePointOfInterestForPoint' per calcolare il punto di messa a fuoco. – Legoless

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

e poi questo:

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

Una versione 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) 
      } 
     } 
    } 
} 
+0

per 'focus_x' e' focus_y' perché dividi per 'width' e' height'? – Crashalot

+0

Ah, leggi questo dai documenti Apple: Inoltre, un dispositivo può supportare un punto di interesse. Testare il supporto utilizzando focusPointOfInterestSupported. Se è supportato, si imposta il punto focale usando focusPointOfInterest. Si passa un CGPoint dove {0,0} rappresenta la parte in alto a sinistra dell'area dell'immagine e {1,1} rappresenta la parte in basso a destra in modalità orizzontale con il pulsante home sulla destra: questo si applica anche se il dispositivo è in modalità verticale . – Crashalot

Problemi correlati