2012-04-19 34 views
13

Tôi có một AVCaptureSession đơn giản đang chạy để lấy nguồn cấp dữ liệu máy ảnh trong ứng dụng của tôi và chụp ảnh. Làm cách nào để tôi có thể triển khai chức năng 'chụm để thu phóng' bằng cách sử dụng máy ảnh UIGestureRecognizer cho máy ảnh?AVCaptureDevice Camera Zoom

+0

Bạn đang thêm cử chỉ chụm vào đâu? – Dalvik

Trả lời

33

Câu trả lời được chấp nhận thực sự đã lỗi thời và tôi không chắc chắn nó sẽ thực sự chụp ảnh của hình ảnh được phóng to. Có một phương pháp để phóng to như câu trả lời bcattle nói. Vấn đề của câu trả lời của anh là nó không chịu trách nhiệm về việc người dùng có thể phóng to và sau đó khởi động lại từ vị trí zoom đó. Giải pháp của anh ta sẽ tạo ra một số bước nhảy không thực sự thanh lịch.

Cách dễ nhất và thanh lịch nhất để thực hiện việc này là sử dụng vận tốc của cử chỉ chụm.

-(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); 
     } 
    } 
} 

Tôi thấy rằng việc thêm hàm arctan vào vận tốc sẽ làm giảm hiệu ứng thu phóng thu phóng một chút. Nó không hoàn toàn chính xác nhưng hiệu quả là đủ tốt cho nhu cầu. Có lẽ có thể là một chức năng để dễ dàng thu nhỏ khi nó gần như đạt đến 1.

LƯU Ý: Ngoài ra, quy mô của một cử chỉ chụm đi từ 0 đến vô hạn với 0-1 con véo vào (thu nhỏ) và 1 đến vô hạn bị véo ra (phóng to). Để có được hiệu ứng phóng to thu nhỏ tốt, bạn cần có phương trình toán học. Vận tốc thực sự từ vô hạn đến vô hạn với 0 là điểm bắt đầu.

EDIT: Đã khắc phục sự cố về phạm vi ngoại lệ. Cảm ơn @garafajon!

+4

Cảm ơn. Sử dụng tính năng này để không nhận được ngoại lệ phạm vi: \t \t \t CGFloat wantZoom = videoDevice.videoZoomFactor + atan (pinchRecognizer.velocity/pinchZoomScaleFactor); \t \t \t videoDevice.videoZoomFactor = MAX (1.0, MIN (mong muốnZoom, videoDevice.activeFormat.videoMaxZoomFactor)); – garafajon

+1

tuyệt vời! Nó hoạt động. – Sourabh

+1

Lưu ý rằng vận tốc có thể trả về nan. Bạn có thể muốn kiểm tra xem trước khi tiếp tục với tính toán: if (isnan (pinchRecognizer.velocity)) {return; } – Masa

6

Nhiều người đã cố gắng thực hiện việc này bằng cách đặt thuộc tính biến đổi trên lớp thành CGAffineTransformMakeScale(gesture.scale.x, gesture.scale.y); Xem here để thực hiện chính xác việc chụm-thu nhỏ.

+0

Cảm ơn bạn đã trả lời. Nhưng làm thế nào để thay đổi quy mô của chế độ xem trước video thực sự thay đổi mức thu phóng của phần cứng máy ảnh? –

+0

Không. Đó là lý do tại sao ngay cả máy ảnh của Apple cũng không thực sự 'phóng to'. Nó chỉ là một số CGAffines, và một số cắt xén ưa thích. – CodaFi

+0

Phải, máy ảnh chỉ sử dụng "zoom kỹ thuật số". Nhưng tôi phải làm gì khác ngoài việc mở rộng chế độ xem trước video để thực sự làm cho hình ảnh được ghi vào đĩa "được thu phóng"? –

4

Vì iOS 7, bạn có thể đặt thu phóng trực tiếp với thuộc tính videoZoomFactor của AVCaptureDevice.

Buộc thuộc tính scale của UIPinchGestureRecognizer thành videoZoomFactor với hằng số mở rộng. Điều này sẽ cho phép bạn thay đổi độ nhạy cảm với mùi vị:

-(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); 
     } 
    } 
} 

Lưu ý rằng AVCaptureDevice, cùng mọi thứ khác liên quan đến AVCaptureSession, không phải là thread an toàn. Vì vậy, bạn có thể không muốn làm điều này từ hàng đợi chính.

-1

Tôi đang sử dụng iOS SDK 8.3 và khuôn khổ AVFoundation và cho tôi sử dụng các phương pháp sau đây làm việc cho:

nameOfAVCaptureVideoPreviewLayer.affineTransform = CGAffineTransformMakeScale(scaleX, scaleY) 

Đối với tiết kiệm hình ảnh với cùng một tỷ lệ tôi đã sử dụng phương pháp sau đây:

nameOfAVCaptureConnection.videoScaleAndCropFactor = factorNumber; 

Mã bên dưới là để lấy hình ảnh ở tỷ lệ

[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { 
     if(imageDataSampleBuffer != NULL){ 

      NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; 
      UIImage *image = [UIImage imageWithData:imageData]; 
} 
}]; 
1

Trong swif Phiên bản t, bạn có thể phóng to/thu nhỏ bằng cách đơn giản chuyển số được chia tỷ lệ lên videoZoomFactor. Mã sau trong trình xử lý UIPinchGestureRecognizer sẽ giải quyết vấn đề.

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 
} 

Ở đây, pivotPinchScale là thuộc tính CGFloat được khai báo trong bộ điều khiển của bạn ở đâu đó.

Bạn cũng có thể tham khảo dự án sau để xem cách máy ảnh hoạt động với UIPinchGestureRecognizer. https://github.com/DragonCherry/CameraPreviewController

0

Swift 4
Thêm một recognizer nhúm cử chỉ cho xem trước nhất và kết nối nó với hành động này (pinchToZoom). captureDevice phải là cá thể hiện đang cung cấp đầu vào cho phiên chụp. pinchToZoom cung cấp khả năng thu phóng mượt mà cho cả hai thiết bị chụp trước & quay lại.

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

Sẽ hữu ích khi khai báo zoomFactor trên máy ảnh hoặc vc của bạn. Tôi thường đặt nó trên cùng một singleton có AVCaptureSession. Điều này sẽ hoạt động như một giá trị mặc định cho videoZoomFactor của captureDevice.

var zoomFactor: Float = 1.0