AVCaptureDevice相机变焦

The*_*ken 19 iphone objective-c ios avcapture avcapturesession

我有一个简单的AVCaptureSession运行,以在我的应用程序中获取相机并拍照.如何使用UIGestureRecognizer相机实现"捏缩放"功能?

Gab*_*ier 42

接受的答案实际上是过时的,我不确定它实际上会拍摄放大图像的照片.有一种放大方法,如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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我发现将arctan函数添加到速度将有助于放大缩小效果.它并不完美,但效果足以满足需求.当它几乎达到1时,可能还有另一个功能可以轻松缩小.

注意:此外,捏合手势的比例从0变为无穷大,0到1被捏入(缩小),1到无限被捏出(放大).要想有一个很好的放大缩小效果,你需要有一个数学方程式.速度实际上是从无限到无穷,0是起点.

编辑:修复范围异常崩溃.感谢@garafajon!

  • 谢谢.使用它来获取范围异常:CGFloat desiredZoom = videoDevice.videoZoomFactor + atan(pinchRecognizer.velocity/pinchZoomScaleFactor); videoDevice.videoZoomFactor = MAX(1.0,MIN(desiredZoom,videoDevice.activeFormat.videoMaxZoomFactor)); (4认同)

Cod*_*aFi 6

许多人试图通过在图层上设置转换属性来实现这一目标,CGAffineTransformMakeScale(gesture.scale.x, gesture.scale.y); 请参阅此处以了解完全成熟的捏合缩放实现.

  • 请参阅[此处](http://stackoverflow.com/a/8166411/945847).只知道没有iOS设备有硬件缩放,所以这需要比我链接到答案的帖子更多的数学. (3认同)

bca*_*tle 5

从iOS 7开始,您可以直接使用videoZoomFactor属性设置缩放AVCaptureDevice

使用缩放常数将的scale属性绑定UIPinchGestureRecognizervideoZoomFactor。这将使您改变口味的敏感性:

-(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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,AVCaptureDevice与以及其他所有相关内容都不AVCaptureSession是线程安全的。因此,您可能不想从主队列中执行此操作。


jnb*_*ard 5

Swift 4
将捏合手势识别器添加到最前面的视图并将其连接到此操作 ( pinchToZoom )。captureDevice应该是当前为捕获会话提供输入的实例。pinchToZoom前后捕获设备提供平滑缩放。

  @IBAction func pinchToZoom(_ pinch: 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
   }
 }
Run Code Online (Sandbox Code Playgroud)

在您的相机或 vc 上声明 zoomFactor 会很有用。我通常把它放在有 AVCaptureSession 的同一个单例上。这将作为captureDevicevideoZoomFactor的默认值。

var zoomFactor: Float = 1.0
Run Code Online (Sandbox Code Playgroud)