AVCaptureDevice相机变焦

我有一个简单的AVCaptureSession运行在我的应用程序中获取相机源并拍照。 我如何使用相机的UIGestureRecognizer实现“捏放大”function?

接受的答案实际上是过时的,我不确定它实际上将放大图像的照片。 有一种方法可以放大像bcattle答案说。 他的回答的问题是,它不承担用户可以放大然后从该缩放位置重新开始的事实。 他的解决scheme将创造一些不是很优雅的跳跃。

最简单和最优雅的方法是使用捏手势的速度。

 -(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时,可能还有其他的function来放大缩小。

注意 :另外,缩小手势的比例从0到无限,0到1被捏入(缩小),1被无限缩小(放大)。 为了得到放大缩小的效果,你需要有一个math公式。 速度实际上是从无限到无限,以0为起点。

编辑 :修复范围exception崩溃。 感谢@garafajon !

许多人都试图通过设置图层上的transform属性为CGAffineTransformMakeScale(gesture.scale.x, gesture.scale.y); 在这里看到一个完整的捏缩放的实现。

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

使用缩放常数将videoZoomFactorscale属性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相关的所有其他内容都不是线程安全的。 所以你可能不希望从主队列中这样做。

在swift版本中,只需在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

斯威夫特4
添加捏手势识别器到最前面的视图,并将其连接到此操作( pinchToZoom )。 captureDevice应该是当前为捕获会话提供input的实例。 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的同一个单例中。 这将作为captureDevicevideoZoomFactor的默认值。

 var zoomFactor: Float = 1.0 

我正在使用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]; } }];