2012-04-19 42 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