#swift #camera #avfoundation #zooming #iphone11
#swift #камера #avfoundation #масштабирование #iphone11
Вопрос:
У меня работает функция масштабирования (1x и далее) для пользовательской камеры, реализованной с использованием AVFoundation. Это нормально до моделей iPhone X. Но я хотел увеличить масштаб в 0,5 раза на устройствах iPhone 11 и iPhone 11 Pro.
Код, который я написал, не работает, чтобы увеличить его до 0,5x. Я перепробовал все возможные комбинации [.builtInTripleCamera, .builtInDualWideCamera, .builtInUltraWideCamera]
. Устройство захвата с типом устройства .builtinUltraWideCamera
не выдает значение 0,5 minAvailableVideoZoomFactor
.
Во время тестирования на iPhone 11 я также удалил [.builtInDualCamera, .builtInTelephotoCamera, .builtInWideAngleCamera, .builtInTrueDepthCamera]
из deviceTypes
.
Ценю любую помощь в решении этой проблемы. Ниже приведен код, который работает для увеличения в 1 раз.
/// Called from -handlePinchGesture
private func zoom(_ scale: CGFloat) {
let captureDevice = cameraDevice(.back)
do {
try captureDevice?.lockForConfiguration()
var minZoomFactor: CGFloat = captureDevice?.minAvailableVideoZoomFactor ?? 1.0
let maxZoomFactor: CGFloat = captureDevice?.maxAvailableVideoZoomFactor ?? 1.0
if #available(iOS 13.0, *) {
if captureDevice?.deviceType == .builtInDualWideCamera || captureDevice?.deviceType == .builtInTripleCamera || captureDevice?.deviceType == .builtInUltraWideCamera {
minZoomFactor = 0.5
}
}
zoomScale = max(minZoomFactor, min(beginZoomScale * scale, maxZoomFactor))
captureDevice?.videoZoomFactor = zoomScale
captureDevice?.unlockForConfiguration()
} catch {
print("ERROR: locking configuration")
}
}
@objc private func handlePinchGesture(_ recognizer: UIPinchGestureRecognizer) {
var allTouchesOnPreviewLayer = true
let numTouch = recognizer.numberOfTouches
for i in 0 ..< numTouch {
let location = recognizer.location(ofTouch: i, in: view)
let convertedTouch = previewLayer.convert(location, from: previewLayer.superlayer)
if !previewLayer.contains(convertedTouch) {
allTouchesOnPreviewLayer = false
break
}
}
if allTouchesOnPreviewLayer {
zoom(recognizer.scale)
}
}
func cameraDevice(_ position: AVCaptureDevice.Position) -> AVCaptureDevice? {
var deviceTypes = [AVCaptureDevice.DeviceType]()
deviceTypes.append(contentsOf: [.builtInDualCamera, .builtInTelephotoCamera, .builtInWideAngleCamera, .builtInTrueDepthCamera])
if #available(iOS 13.0, *) {
deviceTypes.append(contentsOf: [.builtInTripleCamera, .builtInDualWideCamera, .builtInUltraWideCamera])
}
let availableCameraDevices = AVCaptureDevice.DiscoverySession(deviceTypes: deviceTypes, mediaType: .video, position: position).devices
guard availableCameraDevices.isEmpty == false else {
debugPrint("ERROR: No camera devices found!!!")
return nil
}
for device in availableCameraDevices {
if device.position == position {
return device
}
}
guard let defaultDevice = AVCaptureDevice.default(for: AVMediaType.video) else {
debugPrint("ERROR: Can't initialize default back camera!!!")
return nil
}
return defaultDevice
}
Комментарии:
1. Нашли ли вы какое-либо решение, обновив оптический зум до 0,5 x, чтобы использовать сверхширокий объектив в iphone 11 и выше для пользовательских камер?
2. Нет. На данный момент не удалось найти никакого решения.
3. Пожалуйста, используйте это решение — github.com/NextLevel/NextLevel/issues/187 установка типа устройства на ultrawidecamera равна установке 0.5x
Ответ №1:
Обновление для людей, которые хотят установить уровень оптического увеличения 0,5 x
любезно предоставлено: https://github.com/NextLevel/NextLevel/issues/187
public class func primaryVideoDevice(forPosition position: AVCaptureDevice.Position) -> AVCaptureDevice? {
// -- Changes begun
if #available(iOS 13.0, *) {
let hasUltraWideCamera: Bool = true // Set this variable to true if your device is one of the following - iPhone 11, iPhone 11 Pro, amp; iPhone 11 Pro Max
if hasUltraWideCamera {
// Your iPhone has UltraWideCamera.
let deviceTypes: [AVCaptureDevice.DeviceType] = [AVCaptureDevice.DeviceType.builtInUltraWideCamera]
let discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: deviceTypes, mediaType: AVMediaType.video, position: position)
return discoverySession.devices.first
}
}
// -- Changes end
var deviceTypes: [AVCaptureDevice.DeviceType] = [AVCaptureDevice.DeviceType.builtInWideAngleCamera] // builtInWideAngleCamera // builtInUltraWideCamera
if #available(iOS 11.0, *) {
deviceTypes.append(.builtInDualCamera)
} else {
deviceTypes.append(.builtInDuoCamera)
}
// prioritize duo camera systems before wide angle
let discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: deviceTypes, mediaType: AVMediaType.video, position: position)
for device in discoverySession.devices {
if #available(iOS 11.0, *) {
if (device.deviceType == AVCaptureDevice.DeviceType.builtInDualCamera) {
return device
}
} else {
if (device.deviceType == AVCaptureDevice.DeviceType.builtInDuoCamera) {
return device
}
}
}
return discoverySession.devices.first
}
Комментарии:
1. Это не работает. На моем устройстве установлена сверхширокая камера, и по-прежнему невозможно получить 0,5x, используя коэффициент масштабирования.
Ответ №2:
Минимальное свойство «zoomFactor» AVCaptureDevice не может быть меньше 1,0 в соответствии с документами Apple. Это немного сбивает с толку, потому что в зависимости от того, какую камеру вы выбрали, коэффициент масштабирования 1 будет отличаться от поля зрения или угла оптического обзора. Приложение для камеры iPhone по умолчанию показывает метку с надписью «0,5», но это всего лишь метка для сверхширокоугольного объектива по отношению к коэффициенту масштабирования стандартной камеры.
Вы уже получаете MinZoomFactor от устройства (который, вероятно, будет равен 1), поэтому вам следует использовать min и max устройства, которые вы читаете, чтобы установить границы коэффициента, который вы вводите в «captureDevice.videoZoomFactor». Затем, когда вы выбрали сверхширокий объектив, значение коэффициента масштабирования, равное 1, будет максимально широким! (коэффициент 0,5 по отношению к полю обзора стандартного объектива).
Ответ №3:
Проблема в том, что когда вы пытаетесь получить устройство определенного типа, discoverySession.devices
оно возвращает устройство по умолчанию, которое может не поддерживать необходимую вам сверхширокую ширину.
Так было со мной для iPhone 12Pro Max, возвращая только одно устройство для заднего положения, типа отчетности BuiltInWideAngleCamera
, но это была просто ложь, это была средняя камера, не широкая, не телеобъектив. Не знаю, почему разработчики Apple сделали это так, похоже на устаревшую устаревшую архитектуру.
Решение не было очевидным: используйте AVCaptureDevice.default(.builtInTripleCamera, for: .video, position: .back)
, чтобы получить реальное устройство, способное увеличивать масштаб с 1 (ваши логические 0,5).
Комментарии:
1. «Самая широкая» камера 12Pro Max называется встроенной ultravidecamera в коде. Встроенная широкоугольная камера — это «самая стандартная» камера (или «средняя», как вы назвали). Даже единственная камера iPhone 5 (и аналогичная) имеет встроенную широкоугольную камеру в коде. Он назван так, вероятно, потому, что первый iPhone с 2 камерами имеет встроенную широкоугольную камеру и встроенную телефонную фотокамеру
Ответ №4:
Мы не можем установить коэффициент масштабирования меньше 1.
Я решаю эту проблему с помощью «.builtInDualWideCamera».
В этом случае мы используем «Сверхширокоугольную камеру» с коэффициентом масштабирования 2,0 (будет значением по умолчанию), равным нормальному коэффициенту масштабирования на «широкоугольной камере». (минимальное значение будет равно 1,0)
Если ваш iPhone не поддерживает «.builtInDualWideCamera», мы будем использовать «.builtInWideAngleCamera» как обычно, а коэффициент масштабирования равен 1,0 (минимальное значение)
func getCameraDevices() -> [AVCaptureDevice] {
var deviceTypes = [AVCaptureDevice.DeviceType]()
if #available(iOS 13.0, *) {
deviceTypes.append(contentsOf: [.builtInDualWideCamera])
self.isUltraWideCamera = true
self.defaultZoomFactor = 2.0
}
if(deviceTypes.isEmpty){
deviceTypes.append(contentsOf: [.builtInWideAngleCamera])
self.isUltraWideCamera = false
self.defaultZoomFactor = 1.0
}
return AVCaptureDevice.DiscoverySession(deviceTypes: deviceTypes, mediaType: .video, position: .unspecified).devices
}