Спросил об этом на math.stackexchange, но ответов нет, поэтому пытаюсь здесь, надеюсь, люди, занимающиеся компьютерным зрением, смогут помочь.
Предположим, что у меня есть трехмерный круг с центром в (c1, c2, c3)
в системе координат круга C
. Радиус круга равен r
, и есть единичный вектор (v1, v2, v3)
(также в системе координат C
), перпендикулярный плоскости круга в центральной точке.
У меня есть камера-обскура, расположенная в точке (k1, k2, k3)
в системе координат камеры K
. У меня есть известная матрица преобразования системы координат камеры в круг kTc
, которая преобразует любую точку в C
в систему координат K
, так что point_k = np.dot(kTc, point_c)
, где point_k
— точка в системе координат K
, а point_c
— точка в системе координат C
. Камера имеет известную встроенную матрицу камеры I
.
Как спроецировать 3D-круг на плоскость изображения камеры?
В идеале хотелось бы сделать это на питоне.
Спасибо, Саймон, компьютерное зрение также может быть зонтиком, но это вопрос исчисления и координатной геометрии. Не о графике, в основном о преобразовании уравнения с тремя степенями в уравнение с двумя степенями.
Я думаю, вы хотите использовать модуль scipy вместе с numpy. Задача, которую вы решаете, — это преобразование сферы в 2D-плоскость, а затем преобразование этой плоскости (посредством вращения и смещения) в плоскость камеры (какой бы она ни была).
Во-первых, здесь отсутствует некоторая информация о плоскости камеры (фи и/или тета относительно начала координат) или уравнение плоскости и сферы (уравнение сферы в радиальных координатах). Преобразования были бы немного сложными без информации об уравнениях, углах и плоскостях. Я согласен, что вы дали информацию в переменных, но было бы легко иметь под рукой уравнения ИЛИ первым шагом было бы создание уравнений (выполнение этого вручную или с использованием математики и т. д.)
Я буду использовать эту документацию, чтобы попытаться ответить на ваш вопрос - https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.transform.Rotation.html
import numpy as np
from scipy.spatial.transform import Rotation
# Define the center of the circle in the circle coordinate frame
c = np.array([c1, c2, c3])
# Define the normal vector of the circle in the circle coordinate frame
n = np.array([v1, v2, v3])
# Define the camera center in the camera coordinate frame
k = np.array([k1, k2, k3])
# Define the intrinsic camera matrix
I = np.array(..., dtype=np.float32)
# Define the rotation matrix part of kTc
R = np.array(..., dtype=np.float32)
# Define the translation vector part of kTc
t = np.array(..., dtype=np.float32)
# Convert R to a scipy Rotation object
R_obj = Rotation.from_dcm(R)
# Transform the center of the circle to the camera coordinate frame
c_k = R_obj.apply(c) + t
# Project the center of the circle onto the image plane
c_p = I @ c_k
# Normalize the center projection by dividing by its third component
c_p = c_p[:2] / c_p[2]
# Transform the normal vector to the camera coordinate frame
n_k = R_obj.apply(n)
# Project the normal vector onto the image plane
n_p = I[:2, :3] @ n_k
# Normalize the normal projection by dividing by its third component
n_p = n_p / n_p[2]
# Calculate the equation of the circle in the image plane
r_squared = r**2 - np.sum(n_p[:2]**2) / n_p[2]**2
А вот объяснение уравнений, используемых в коде:
c = np.array([c1, c2, c3]): The center of the circle in the circle coordinate frame is represented by the vector c = [c1, c2, c3].
n = np.array([v1, v2, v3]): The normal vector of the circle in the circle coordinate frame is represented by the vector n = [v1, v2, v3].
k = np.array([k1, k2, k3]): The camera center in the camera coordinate frame is represented by the vector k = [k1, k2, k3].
I = np.array(..., dtype=np.float32): The intrinsic camera matrix is represented by the 2D array I.
R = np.array(..., dtype=np.float32): The rotation matrix part of the kTc transformation matrix is represented by the 3x3 array R.
t = np.array(..., dtype=np.float32): The translation vector part
Преобразуйте трехмерный круг из системы координат круга (C) в систему координат камеры (K), используя матрицу преобразования kTc. Центр преобразованного круга будет задан:
center_k = np.dot (kTc, [c1, c2, c3, 1])
Спроецируйте центр преобразованного круга на плоскость изображения камеры, используя внутреннюю матрицу камеры I. Проекция центра будет определяться как:
center_p = np.dot (I, center_k)
Преобразуйте вектор нормали из системы координат круга (C) в систему координат камеры (K), используя матрицу преобразования kTc. Преобразованный вектор нормали будет иметь вид:
normal_k = np.dot(kTc[:3, :3], [v1, v2, v3])
Спроецируйте преобразованный вектор нормали на плоскость изображения камеры, используя внутреннюю матрицу камеры I. Проекция вектора нормали будет иметь вид:
normal_p = np.dot(I[:2,:3], normal_k)
Теперь, используя центральную и нормальную проекции, вы можете найти уравнение 2D-окружности в плоскости изображения камеры. Уравнение окружности в плоскости изображения будет иметь вид:
(x - center_p[0]/center_p[2])^2 + (y - center_p[1]/center_p[2])^2 = r^2 - (normal_p[0]^2 + normal_p[1]^2 )/(нормаль_р[2]^2)
где (x, y) — координаты плоскости изображения проецируемого круга.
Обратите внимание, что вам нужно будет нормализовать центральную и нормальную проекции, разделив каждую на их соответствующие третьи компоненты (center_p[2] и normal_p[2]), чтобы получить их фактические координаты плоскости изображения.
Я рекомендую посмотреть этот вопрос и ответы на него на Gamedev: gamedev.stackexchange.com/questions/188076/…