CameraIntrinsics.UndistortedProjectionTransform 属性

定义

获取一个矩阵,该矩阵将图像平面上的 2D 坐标(以米为单位)转换为视频帧像素坐标,而无需补偿相机的失真模型。 除非应用应用自己的失真补偿,否则此转换产生的 2D 点将无法准确映射到视频帧中的像素坐标。 这对于选择实现基于 GPU 的失真补偿而不是使用 UndistortPoint 的应用非常有用,后者使用 CPU 来计算失真补偿。

public:
 property float4x4 UndistortedProjectionTransform { float4x4 get(); };
float4x4 UndistortedProjectionTransform();
public Matrix4x4 UndistortedProjectionTransform { get; }
var matrix4x4 = cameraIntrinsics.undistortedProjectionTransform;
Public ReadOnly Property UndistortedProjectionTransform As Matrix4x4

属性值

Matrix4x4 Matrix4x4

float4x4

获取一个矩阵,该矩阵将图像平面上的 2D 坐标(以米为单位)转换为视频帧像素坐标,而无需补偿相机的失真模型。

Windows 要求

设备系列
Windows 10 Anniversary Edition (在 10.0.14393.0 中引入)
API contract
Windows.Foundation.UniversalApiContract (在 v3.0 中引入)

注解

转换从图像平面上以米为单位的 2D 坐标转换为主点 (原点,+X 指向右侧,+Y 指向) ,转换为以像素为单位的 2D 坐标,原点位于图像左上角,+X 指向右侧,+Y 指向下。 如果 2D 坐标表示为具有四个分量的向量,则 Z 必须设置为 0,W 必须设置为 1。

若要将相机坐标系中的 3D 坐标转换为像素坐标,必须先将坐标的 X 和 Y 分量除以与相机 (的距离,即 Z 坐标) 才能将它们投影到图像平面上。 请注意,相机坐标系按约定是右手的,+X 向右指,+Y 指向上,-Z 通过图像的中心 (主点) 从相机指向。 在该约定中,Z 坐标在划分为 X 和 Y 分量时必须求反。 例如:

using namespace winrt::Windows::Foundation::Numerics;
winrt::Windows::Foundation::Point ProjectCameraCoordinateToPixelCoordinate(
    const winrt::Windows::Media::Devices::Core::CameraIntrinsics& cameraIntrinsics,
    const float3& cameraCoordinate)
{
    const float2 imagePlaneCoordinate = float2{ cameraCoordinate.x / -cameraCoordinate.z, cameraCoordinate.y / -cameraCoordinate.z };
    float2 pixelCoordinate = transform(imagePlaneCoordinate, cameraIntrinsics.UndistortedProjectionTransform());
    return winrt::Windows::Foundation::Point{ pixelCoordinate.x, pixelCoordinate.y };
}

通过将 Z 分量设置为 1,将 W 分量设置为离相机的距离,可以使用具有四个分量的矢量来实现等效的结果。 请注意,生成的 X 和 Y 分量必须除以生成的 W 分量才能生成最终像素坐标:

using namespace winrt::Windows::Foundation::Numerics;
winrt::Windows::Foundation::Point ProjectCameraCoordinateToPixelCoordinate(
    const winrt::Windows::Media::Devices::Core::CameraIntrinsics& cameraIntrinsics,
    const float3& cameraCoordinate)
{
    float4 cameraCoordinateVector{ cameraCoordinate.x, cameraCoordinate.y, 1, -cameraCoordinate.z };
    float4 pixelCoordinate = transform(cameraCoordinateVector, cameraIntrinsics.UndistortedProjectionTransform());
    return winrt::Windows::Foundation::Point{ pixelCoordinate.x / pixelCoordinate.w, pixelCoordinate.y / pixelCoordinate.w };
}

如果此转换将应用于许多 3D 坐标,则调整矩阵本身比每个输入坐标更方便。 这可以通过交换矩阵的第三行和第四行,并使用同质坐标转换函数(如 XMVector3TransformCoordStream)来实现。 请注意,右手到左手转换也作为转换的一部分应用,以便与相机的距离为正值:

using namespace DirectX;
void ProjectCameraCoordinatesToPixelCoordinates(
    const winrt::Windows::Media::Devices::Core::CameraIntrinsics& cameraIntrinsics,
    const winrt::array_view<XMFLOAT3>& cameraCoordinates,
    winrt::array_view<winrt::Windows::Foundation::Point>& pixelCoordinates)
{
    XMMATRIX undistortedProjectionTransform = XMLoadFloat4x4(&cameraIntrinsics.UndistortedProjectionTransform());
    std::swap(undistortedProjectionTransform.r[2], undistortedProjectionTransform.r[3]);

    // convert right-handed coordinates (-Z forward) to right-handed coordinates (+Z forward) as part of the transform
    static const XMMATRIX rightToLeft = XMMatrixScaling(1, 1, -1);

    std::vector<XMFLOAT3> pixelCoordinateVectors(cameraCoordinates.size());
    XMVector3TransformCoordStream(
        pixelCoordinateVectors.data(), sizeof(pixelCoordinateVectors[0]),
        cameraCoordinates.data(), sizeof(cameraCoordinates[0]), cameraCoordinates.size(),
        rightToLeft * undistortedProjectionTransform);

    std::transform(pixelCoordinateVectors.begin(), pixelCoordinateVectors.end(), pixelCoordinates.begin(),
        [](const XMFLOAT3& v) { return winrt::Windows::Foundation::Point{ v.x, v.y }; });
}

适用于