2012-04-19 73 views
13

我有一個簡單的AVCaptureSession運行在我的應用程序中獲取相機饋送並拍照。我如何使用UIGestureRecognizer來實現相機的「縮放變焦」功能?AVCaptureDevice相機變焦

+0

你要添加捏手勢? – Dalvik 2017-10-01 18:25:36

回答

33

接受的答案實際上已過時,我不確定它實際上是否會放大圖像的照片。有一種方法可以放大像bcattle答案所述。他的回答問題是,它不承擔用戶可以放大然後從該縮放位置重新啓動的事實。他的解決方案會創造出一些不太優雅的跳躍。

這樣做的最簡單和最優雅的方式是使用捏手勢的速度。

-(void) handlePinchToZoomRecognizer:(UIPinchGestureRecognizer*)pinchRecognizer { 
    const CGFloat pinchVelocityDividerFactor = 5.0f; 

    if (pinchRecognizer.state == UIGestureRecognizerStateChanged) { 
     NSError *error = nil; 
     if ([videoDevice lockForConfiguration:&error]) { 
      CGFloat desiredZoomFactor = device.videoZoomFactor + atan2f(pinchRecognizer.velocity, pinchVelocityDividerFactor); 
      // Check if desiredZoomFactor fits required range from 1.0 to activeFormat.videoMaxZoomFactor 
      device.videoZoomFactor = MAX(1.0, MIN(desiredZoomFactor, device.activeFormat.videoMaxZoomFactor)); 
      [videoDevice unlockForConfiguration]; 
     } else { 
      NSLog(@"error: %@", error); 
     } 
    } 
} 

我發現將arctan函數添加到速度會緩解放大縮小效果。它不完美,但效果足以滿足需求。也許有可能是另一種功能,緩解變焦出來的時候,幾乎達到1

注意:另外,捏合手勢的規模從0到無窮以0比1的存在捏在(縮小)和1到無限張開(放大)。爲了獲得放大縮小效果,你需要有一個數學公式。速度實際上是從無限到無限,以0爲起點。

編輯:修復了範圍異常的崩潰。感謝@garafajon

+4

謝謝。使用它不會得到範圍異常:\t \t \t CGFloat desiredZoom = videoDevice.videoZoomFactor + atan(pinchRecognizer.velocity/pinchZoomScaleFactor); \t \t \t videoDevice.videoZoomFactor = MAX(1.0,MIN(desiredZoom,videoDevice.activeFormat.videoMaxZoomFactor)); – garafajon 2015-10-01 18:32:08

+1

太棒了!有用。 – Sourabh 2015-12-08 12:34:07

+1

請注意,速度可以返回nan。你可能想在繼續計算之前檢查一下:if(isnan(pinchRecognizer.velocity)){return; } – Masa 2016-03-15 08:54:33

6

許多人都試圖通過將圖層上的transform屬性設置爲CGAffineTransformMakeScale(gesture.scale.x, gesture.scale.y); 請參閱here,以獲得完整的縮放縮放實現。

+0

感謝您的回覆。但是,僅僅改變視頻預覽視圖的縮放比例實際上會改變攝像機硬件的縮放比例? – 2012-04-19 03:12:21

+0

它沒有。這就是爲什麼即使蘋果的相機不真正'放大'。這只是一些CGAffines,還有一些奇特的種植。 – CodaFi 2012-04-19 03:17:11

+0

對,相機只是使用「數碼變焦」。但是除縮放視頻預覽視圖之外,我還必須做些什麼才能真正將圖像寫入磁盤「縮放」? – 2012-04-19 03:42:12

4

從iOS 7開始,您可以使用AVCaptureDevicevideoZoomFactor屬性直接設置縮放。

UIPinchGestureRecognizerscale屬性與縮放常數結合爲videoZoomFactor。這將讓你改變靈敏度的味道:

-(void) handlePinchToZoomRecognizer:(UIPinchGestureRecognizer*)pinchRecognizer { 
    const CGFloat pinchZoomScaleFactor = 2.0; 

    if (pinchRecognizer.state == UIGestureRecognizerStateChanged) { 
     NSError *error = nil; 
     if ([videoDevice lockForConfiguration:&error]) { 
      videoDevice.videoZoomFactor = 1.0 + pinchRecognizer.scale * pinchZoomScaleFactor; 
      [videoDevice unlockForConfiguration]; 
     } else { 
      NSLog(@"error: %@", error); 
     } 
    } 
} 

注意AVCaptureDevice,沿一切有關AVCaptureSession,不是線程安全的。所以你可能不想從主隊列中做到這一點。

-1

我使用的是iOS SDK 8.3和AVfoundation框架和我使用下面的方法處理爲:

nameOfAVCaptureVideoPreviewLayer.affineTransform = CGAffineTransformMakeScale(scaleX, scaleY) 

對於保存照片與我用下面的方法相同規模:

nameOfAVCaptureConnection.videoScaleAndCropFactor = factorNumber; 

代碼波紋管是在尺度

[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { 
     if(imageDataSampleBuffer != NULL){ 

      NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; 
      UIImage *image = [UIImage imageWithData:imageData]; 
} 
}]; 
1

在SWIF獲取圖像t版本,只需在videoZoomFactor上傳遞縮放數字即可放大/縮小。以下UIPinchGestureRecognizer處理程序中的代碼將解決此問題。

do { 
    try device.lockForConfiguration() 
    switch gesture.state { 
    case .began: 
     self.pivotPinchScale = device.videoZoomFactor 
    case .changed: 
     var factor = self.pivotPinchScale * gesture.scale 
     factor = max(1, min(factor, device.activeFormat.videoMaxZoomFactor)) 
     device.videoZoomFactor = factor 
    default: 
     break 
    } 
    device.unlockForConfiguration() 
} catch { 
    // handle exception 
} 

在這裏,pivotPinchScale是一個CGFloat屬性,它在控制器的某個地方聲明。

您也可以參考以下項目瞭解相機如何與UIPinchGestureRecognizer配合使用。 https://github.com/DragonCherry/CameraPreviewController

0

夫特4
添加捏手勢識別到最前視圖,並將其連接到這個動作(pinchToZoom)。 captureDevice應該是當前爲捕獲會話提供輸入的實例。 pinchToZoom可爲前端&後端提供平滑縮放捕捉設備。

@IBAction func pinchToZoom(_ sender: UIPinchGestureRecognizer) { 

    guard let device = captureDevice else { return } 

    func minMaxZoom(_ factor: CGFloat) -> CGFloat { return min(max(factor, 1.0), device.activeFormat.videoMaxZoomFactor) } 

    func update(scale factor: CGFloat) { 
     do { 
     try device.lockForConfiguration() 
     defer { device.unlockForConfiguration() } 
     device.videoZoomFactor = factor 
     } catch { 
     debugPrint(error) 
     } 
    } 

    let newScaleFactor = minMaxZoom(pinch.scale * zoomFactor) 

    switch sender.state { 
     case .began: fallthrough 
     case .changed: update(scale: newScaleFactor) 
     case .ended: 
     zoomFactor = minMaxZoom(newScaleFactor) 
     update(scale: zoomFactor) 
    default: break 
    } 
} 

在攝像頭或vc上聲明zoomFactor會很有用。我通常把它放在具有AVCaptureSession的同一個單例中。這將作爲CaptureDevice的videoZoomFactor的默認值。

var zoomFactor: Float = 1.0