我已经与projectPoints斗争了好几天,但不了解该功能的基本参考点。我发现很难找到单词坐标和所有输入的参考点。
这是一个小例子。
import numpy as np
import cv2 as cv
camera_matrix = np.array([
[1062.39, 0., 943.93],
[0., 1062.66, 560.88],
[0., 0., 1.]
])
points_3d = xyz_to_np_point(10, 0, 0)
rvec = np.zeros((3, 1), np.float32)
tvec = np.zeros((3, 1), np.float32)
dist_coeffs = np.zeros((5, 1), np.float32)
points_2d, _ = cv.projectPoints(points_3d,
rvec, tvec,
camera_matrix,
dist_coeffs)
print(points_2d)
相机没有旋转,因此 rvec=(0,0,0),我们将相机位置作为世界的原点,使得 tvec=(0,0,0)。然后将我们要计算 3D 到 2D 的对象放置在相机前面 10 个单位处。
这里有一个例子:
代码的输出是 (11567.83 560.88) 而不是我期望的 (0,0)。
更长的解释。我正在尝试在我的图像中投影船舶的位置。我有相机和船只的 GPS 位置。我通过获取 X 轴上的距离(东边的 X 点)和 Y 轴上的距离(北边的 Y 点)将 GPS 坐标转换为平面。由于船只分配在海平面上方,因此我将 3D 点投影为 (X, Y, 0)
对于相机的外部参数,我假设相机再次是参考世界,并且 tvec 仅考虑相机相对于海平面的高度(tvec = (0,0,4))。作为旋转,我有一个绝对 IMU,因此我可以计算 X acis 上的 rvec(为简单起见,相机平行于 XY 平面)。
我已经完成了相机校准并获得了我的相机矩阵和畸变系数。不知道如何测试相机矩阵,但我发现使用畸变系数对图像进行去畸变,我的图像可以获得线性车道并消除畸变。
这里是我的问题的代码和一些示例。
import numpy as np
import cv2 as cv
from scipy.spatial.transform import Rotation as R
from haversine import haversine, Unit
def distance_between_coordinates(c1, c2):
x = haversine(c1, (c1[0], c2[1]), Unit.METERS)
if c1[1] > c2[1]:
x = -x
y = haversine(c1, (c2[0], c1[1]), Unit.METERS)
if c1[1] > c2[1]:
y = -y
dist = haversine(c1, c2, Unit.METERS)
return dist, x, y
def rotvec_from_euler(orientation):
r = R.from_euler('xyz', [orientation[0], orientation[1], orientation[2]], degrees=True)
return r.as_rotvec()
if __name__ == '__main__':
camera_matrix = np.array([
[1062.39, 0., 943.93],
[0., 1062.66, 560.88],
[0., 0., 1.]
])
dist_coeffs = np.array([-0.33520254, 0.14872426, 0.00057997, -0.00053154, -0.03600385])
camera_p = (37.4543785, 126.59113666666666)
ship_p = (37.448312, 126.5781)
# Other ships near to the previous one.
# ship_p = (37.450693, 126.577617)
# ship_p = (37.4509, 126.58565)
# ship_p = (37.448635, 126.578202)
camera_orientation = (206.6925, 0, 0) # Euler orientation.
rvec = rotvec_from_euler(camera_orientation)
tvec = np.zeros((3, 1), np.float32)
_, x, y = distance_between_coordinates(camera_p, ship_p)
points_3d = np.array([[[x, y, 0]]], np.float32)
points_2d, _ = cv.projectPoints(points_3d,
rvec, tvec,
camera_matrix,
dist_coeffs)
print(points_2d)
我得到了更多坐标,这些坐标是在同一方向附近的船只,并且应该靠近相机的中心。如果您还尝试其他项目点的预测会发生巨大变化。
为了清楚起见,我添加了第二个代码块的坐标系的图示。
首先应该检查一下OpenCV中坐标系的定义。
尝试投影点 (10,0,0) 是无稽之谈。
如果您使用正确的输入 (0,0,10),输出将为 (943.93, 560.88),而不是 (0,0)。