-->

AVCaptureDevice相机变焦(AVCaptureDevice Camera Zoom)

2019-07-29 01:57发布

我有一个简单AVCaptureSession运行让我的应用程序摄像机的输入和拍照。 我怎样才能实现“捏缩放”功能使用UIGestureRecognizer相机?

Answer 1:

该接受的答案实际上是过时的,我不知道它实际上将图像放大后的照片。 有放大像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);
        }
    }
}

我发现,加入反正切函数的速度将缓解放大出来的效果变焦位。 这不完全是完美的,但效果是需求不够好。 也许有可能是另一种功能,缓解变焦出来的时候,几乎达到1。

注意 :另外,捏手势的刻度从0到无穷大,用0至1的存在夹持在(缩小)和1至无限的空间中捏出(放大)。 为了得到变焦良好的变焦效果出来这个你需要有一个数学方程式。 速度实际上是无穷大与0为出发点,以无限的。

编辑 :在范围例外固定崩溃。 感谢@garafajon !



Answer 2:

许多人试图通过设置层的transform属性做到这一点CGAffineTransformMakeScale(gesture.scale.x, gesture.scale.y); 见这里的羽翼丰满实现双指缩放。



Answer 3:

由于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);
        }
    }
}

需要注意的是AVCaptureDevice ,沿一切有关AVCaptureSession ,不是线程安全的。 所以,你可能不希望从主队列中做到这一点。



Answer 4:

斯威夫特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
   }
 }

这将是宣布zoomFactor相机或VC非常有用。 我通常把它放在有AVCaptureSession相同的单。 这将作为captureDevice的videoZoomFactor的默认值。

var zoomFactor: Float = 1.0


Answer 5:

在迅速的版本,你可以通过简单地传递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



Answer 6:

我从@Gabriel卡地亚的解决方案(感谢)开始。 在我的代码,我最好使用平滑rampToVideoZoomFactor和更简单的方法来计算设备的比例因子。

(IBAction) pinchForZoom:(id) sender forEvent:(UIEvent*) event {
    UIPinchGestureRecognizer* pinchRecognizer = (UIPinchGestureRecognizer *)sender;

    static CGFloat zoomFactorBegin = .0;
    if ( UIGestureRecognizerStateBegan == pinchRecognizer.state ) {
        zoomFactorBegin = self.captureDevice.videoZoomFactor;

    } else if (UIGestureRecognizerStateChanged == pinchRecognizer.state) {
        NSError *error = nil;
        if ([self.captureDevice lockForConfiguration:&error]) {

            CGFloat desiredZoomFactor = zoomFactorBegin * pinchRecognizer.scale;
            CGFloat zoomFactor = MAX(1.0, MIN(desiredZoomFactor, self.captureDevice.activeFormat.videoMaxZoomFactor));
            [self.captureDevice rampToVideoZoomFactor:zoomFactor withRate:3.0];

            [self.captureDevice unlockForConfiguration];
        } else {
            NSLog(@"error: %@", error);
        }
    }
}


Answer 7:

基于@Gabriel卡地亚的回答:

- (void) cameraZoomWithPinchVelocity: (CGFloat)velocity {
    CGFloat pinchVelocityDividerFactor = 40.0f;
    if (velocity < 0) {
        pinchVelocityDividerFactor = 5.; //zoom in
    }

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


Answer 8:

我使用的是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];
}
}];


文章来源: AVCaptureDevice Camera Zoom