2012-04-19 6 views
13

У меня есть простой AVCaptureSession, который работает, чтобы получить канал камеры в моем приложении и делать фотографии. Как я могу реализовать функциональность «щепотка для увеличения», используя UIGestureRecognizer для камеры?AVCaptureDevice Camera Zoom

+0

Куда вы добавляете пинч-жест? – Dalvik

ответ

33

Принятый ответ на самом деле устарел, и я не уверен, что он фактически сделает снимок увеличенного изображения. Существует метод увеличения масштаба, например, ответ на битков. Проблема его ответа заключается в том, что он не берет на себя ответственность за то, что пользователь может увеличить масштаб, а затем возобновить работу с этой позиции масштабирования. Его решение создаст какие-то прыжки, которые не очень элегантны.

Самый простой и элегантный способ сделать это - использовать скорость жестов щепотка.

-(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 - исходная.

EDIT: Исправлена ​​ошибка при превышении допустимого диапазона. Благодаря @garafajon!

+4

Спасибо. Используйте это, чтобы не получить исключение диапазона: \t \t \t CGFloat wishZoom = videoDevice.videoZoomFactor + atan (pinchRecognizer.velocity/pinchZoomScaleFactor); \t \t \t videoDevice.videoZoomFactor = MAX (1.0, MIN (желательноZoom, видеоDevice.activeFormat.videoMaxZoomFactor)); – garafajon

+1

замечательный! Оно работает. – Sourabh

+1

Помните, что скорость может возвращать nan. Возможно, вы захотите проверить это, прежде чем переходить к вычислению: if (isnan (pinchRecognizer.velocity)) {return; } – Masa

6

Многие попытались сделать это, установив свойство преобразования на слой на CGAffineTransformMakeScale(gesture.scale.x, gesture.scale.y); См. here для полноценной реализации масштабирования.

+0

Спасибо за ответ. Но как просто изменение масштаба просмотра видеоизображения фактически меняет масштаб аппаратного обеспечения камеры? –

+0

Это не так. Вот почему даже камера Apple по-настоящему не масштабируется. Это всего лишь некоторые CGAffines, и некоторые причудливые кадрирования. – CodaFi

+0

Правильно, камера просто использует «цифровой зум». Но что еще я должен делать за пределами масштабирования вида предварительного просмотра видео, чтобы на самом деле сделать изображение записываемым на диск «увеличенным»? –

4

С iOS 7 вы можете установить масштаб напрямую с помощью свойства videoZoomFactorAVCaptureDevice.

Свяжите scale имущество UIPinchGestureRecognizer с 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

Swift 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 
    } 
} 

Будет полезно объявить zoomFactor на вашей камере или в. Обычно я помещаю его в один синглтон с AVCaptureSession. Это будет действовать в качестве значения по умолчанию для videoZoomFactor.

var zoomFactor: Float = 1.0 

 Смежные вопросы

  • Нет связанных вопросов^_^