Или вы можете просто сделать:

ользую ARSCNView от ARKit для показа живого видео с камеры на iPad. У меня есть объект ARSCNView, настроенный точно так же, как шаблон приложения дополненной реальности XCode. Мне было интересно, есть ли способ получить поле зрения камеры?

@IBOutlet var sceneView: ARSCNView!

func start() {
    sceneView.delegate = self
    sceneView.session.run(ARWorldTrackingConfiguration())
    // Retrieve camera FOV here
}
 chengsam29 нояб. 2017 г., 16:35
Как насчетsceneView.pointOfView?.camera?.xFov?

Ответы на вопрос(2)

sceneView.pointOfView?.camera?.fieldOfView
Решение Вопроса

и возможный фальстарт, чтобы остерегаться.

⚠️ ARKit + SceneKit (неверно)

Если вы уже работаете с ARKit через SceneKit (ARSCNView), вы можете предположить, что ARKit автоматически обновляет камеру SceneKit (представлениеpointOfView«scamera), чтобы соответствовать преобразованию проекции, используемому ARKit. Это верно.

Тем не менее, ARKit напрямую устанавливаетSCNCamera«sprojectionTransform, Когда вы работаете с геометрическими свойствамиSCNCamera любитьzNear а такжеzFar а такжеfieldOfViewSceneKit получает матрицу проекции для использования при рендеринге. Но если вы установитеprojectionTransform напрямую, нет математики, которая может восстановить значения ближнего / дальнего и xFov / yFov, поэтому соответствующиеSCNCamera свойства недействительны. Это,sceneView.pointOfView.camera.fieldOfView и подобные API всегда возвращают фиктивные результаты для приложения ARKit.

Итак, что вы можете сделать вместо этого? Читать дальше...

Проекционная матрица

AR сессия постоянно торгуетARFrame объекты через своего делегата, или вы можете запроситьcurrentFrame от него. Каждый кадр имеетARCamera прилагается, который описывает параметры изображения, один из которых являетсяprojectionMatrix это зависит от поля зрения. (Есть также вышеупомянутый SceneKitprojectionTransform, которая является той же матрицей.)

Стандартная матрица трехмерного проецирования включает в себя условия масштабирования, основанные на вертикальном поле зрения и соотношении сторон. В частности, матрица выглядит так:

[ xScale    0     0    0  ]   xScale = yScale * aspectRatio (width/height)
[   0    yScale   0    0  ]   yScale = 1 / tan(yFov/2)
[   0       0    nf1  nf2 ]   nf1 and nf2 relate to near and far clip planes,
[   0       0     -1   0  ]     so aren't relevant to field of view

Таким образом, вы должны быть в состоянии получитьyFov решаяyScale уравнение:

let projection = session.currentFrame!.camera.projectionMatrix
let yScale = projection[1,1]
let yFov = 2 * atan(1/yScale) // in radians
let yFovDegrees = yFov * 180/Float.pi

А для горизонтального поля зрения вы можете умножить на соотношение сторон (в частности, соотношение ширины / высоты):

let imageResolution = session.currentFrame!.camera.imageResolution
let xFov = yFov * Float(imageResolution.width / imageResolution.height)

Примечание: Здесь «горизонтальный» и «вертикальный» относятся к изображению с камеры, которое изначально находится в горизонтальной ориентации независимо от того, как ориентировано ваше устройство или интерфейс просмотра AR.

Если вы посмотрите внимательно, вы можете заметить, что соотношение сторон междуxFov/yFov здесь (и соотношение сторонimageResolution) не обязательно соответствуют экрану вашего устройства (особенно на iPhone X) или виду, в котором вы рисуете контент AR. Это потому, что вы измерили углы обзора.изображения с камерыа не те, что в AR вашего приложения. Не волнуйтесь, для этого тоже есть API ...

Матрица проекции с окном просмотра

ARCamera предлагает два API для получения матрицы проекции. Помимо того, что мы только что прошли, есть такжеprojectionMatrix(for:viewportSize:zNear:zFar:), который принимает презентацию во внимание. Если вы хотите сопоставить не поле зрения камеры, а поле зрения того, какARSCNView или жеARSKView (или Unity или Unreal, возможно?) визуализируют вашу AR-сцену, используйте ее, передавая ориентацию устройства и видя ваш взгляд. Затем сделайте все то же самое, что и выше:

let imageResolution = session.currentFrame!.camera.imageResolution
let viewSize = sceneView.bounds.size
let projection = session.currentFrame!.camera.projectionMatrix(for: .portrait,
    viewportSize: viewSize, zNear: zNear, zFar: zFar)
let yScale = projection[1,1] // = 1/tan(fovy/2)
let yFovDegrees = 2 * atan(1/yScale) * 180/Float.pi
let xFovDegrees = yFovDegrees * Float(viewSize.height / viewSize.width)

За что вы проходитеzNear а такжеzFar не имеет значения, так как мы не используем части матрицы, которые зависят от этого. (Вам все еще может потребоватьсяzNear < zFar а такжеzNear != zFar != 0.)

Примечание: Теперь высота / ширина зависят от вашего вида (точнее, от атрибутов вашего вида, которые вы передаетеprojectionMatrix(for:...)). В этом примереyFov вертикально по отношению к пользовательскому интерфейсу, потому что ориентацияportrait, так что вы умножаете на соотношение сторон высоты / ширины, чтобы получитьxFov, Если вы находитесь в альбомной ориентации, вы вместо этого умножаетесь на ширину / высоту.

Встроенная камера

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

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

let imageResolution = session.currentFrame!.camera.imageResolution
let intrinsics = session.currentFrame!.camera.intrinsics
let xFovDegrees = 2 * atan(Float(imageResolution.width)/(2 * intrinsics[0,0])) * 180/Float.pi
let yFovDegrees = 2 * atan(Float(imageResolution.height)/(2 * intrinsics[1,1])) * 180/Float.pi

Примечание: Как версия, которая используетprojectionMatrix, это основано на размере и всегда-альбомной ориентацииизображение с камеры, а не на экране устройства или в представлении, в котором отображается контент AR. Если вам нужно что-то на основе области просмотра, прокрутите обратно до «Матрица проецирования с окном просмотра».

 Rhythmic Fistman18 июн. 2018 г., 21:44
Это лучший ответ на Земле.
 Damian Dudycz18 июл. 2018 г., 17:01
Это помогло мне понять, почему я получаю ошибки в какой-то другой задаче. У меня AR-движок, написанный с использованием SceneKit и предварительного просмотра камеры (более простая версия ark), и у меня проблема с масштабированием объектов в нем. Я использовал для установки fieldOfView в SceneKit для точного fieldOfView формата камеры (около 58), и объекты выглядели слишком большими. Теперь, печатая значения ARKit, как вы описали, я вижу, что, когда камера фокусируется на другом расстоянии, это поле тоже изменяется. Это объяснило бы, почему масштаб моих объектов был немного отклонен.
 Andrew21 июн. 2018 г., 10:45
Действительно полезно. 2 вопроса - 1. Есть ли способ узнать горизонтальное поле зрения? то есть, если бы пользователь указывал камеру прямо вперед, что бы там было FOV? 2. Я проверил это, добавив 360 узлов к моей сцене вокруг пользователя. В результате я смог увидеть 31 из них, но xFOVDegrees вернул 45 или 60, в зависимости от того, какой из 2 нижних методов я использовал. Так что можно предположить, что xFOV на самом деле 31?
 Damian Dudycz18 июл. 2018 г., 17:03
Вы случайно не знаете, как я могу настроить этот FieldOfView, который я читаю из cameraFormat, на текущий фокус камеры, чтобы он выглядел правильно? Я прочитал значение более 58 градусов и думаю, что мне нужно умножить это на какое-то значение из сеанса камеры или применить другое исправление, но я не знаю, где его искать.

Ваш ответ на вопрос