2012-10-26 50 views
22

我想創建一個相機應用程序,它會像默認相機應用程序或多或少一樣。 目前不適合我的東西是點擊重點。我希望照相機能夠專注於我的觸摸點,並像做真正的照相機應用那樣做。ios AVFoundation點擊焦點

這裏是我的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); 
    }]; 
} 

一旦我點擊屏幕,什麼也沒有發生。

回答

31

你必須接觸點調整到範圍[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}代表右側的Home按鈕在橫向模式下的右下角,即使設備處於縱向模式。

+0

是否有解釋爲什麼這需要這樣做了文檔什麼的? – spacecash21

+0

更新了答案以指向Apple提供的文檔。 –

+19

您也可以使用'AVCaptureVideoPreviewLayer'和'captureDevicePointOfInterestForPoint'方法來計算焦點。 – Legoless

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

迅速版本:

@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

for'focus_x'和'focus_y'爲什麼用'width'和'height'來劃分? – Crashalot

+0

嗯,剛剛從Apple文檔中閱讀:此外,一個設備可能支持一個重點關注點。您使用focusPointOfInterestSupported測試支持。如果支持,則使用focusPointOfInterest設置焦點。您傳遞一個CGPoint,其中{0,0}代表圖片區域的左上角,{1,1}代表右側的Home按鈕在橫向模式下的右下角,即使設備處於縱向模式。 – Crashalot