Compartir a través de


CameraIntrinsics.UndistortedProjectionTransform Propiedad

Definición

Obtiene una matriz que transforma una coordenada 2D en metros del plano de imagen en coordenadas de píxeles de fotograma de vídeo sin compensar el modelo de distorsión de la cámara. El punto 2D resultante de esta transformación no se asignará con precisión a la coordenada de píxel en un fotograma de vídeo a menos que la aplicación aplique su propia compensación de distorsión. Esto es útil para las aplicaciones que eligen implementar la compensación de distorsión basada en GPU en lugar de usar UndistortPoint, que usa la CPU para calcular la compensación de distorsión.

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

Valor de propiedad

Matrix4x4 Matrix4x4

float4x4

Obtiene una matriz que transforma una coordenada 2D en metros del plano de imagen a las coordenadas de píxeles del fotograma de vídeo sin compensar el modelo de distorsión de la cámara.

Requisitos de Windows

Familia de dispositivos
Windows 10 Anniversary Edition (se introdujo en la versión 10.0.14393.0)
API contract
Windows.Foundation.UniversalApiContract (se introdujo en la versión v3.0)

Comentarios

La transformación se convierte de una coordenada 2D en metros del plano de imagen (origen en el punto principal, +X que apunta a la derecha y +Y hacia arriba), a una coordenada 2D en píxeles con el origen en la esquina superior izquierda de la imagen, y +X que apunta a la derecha y +Y apuntando hacia abajo. Si la coordenada 2D se expresa como un vector con cuatro componentes, Z debe establecerse en 0 y W debe establecerse en 1.

Para convertir una coordenada 3D en el sistema de coordenadas de la cámara en coordenadas de píxeles, los componentes X e Y de la coordenada deben dividirse primero por la distancia desde la cámara (es decir, la coordenada Z) para proyectarlas en el plano de imagen. Tenga en cuenta que los sistemas de coordenadas de cámara están a la derecha por convención, con +X apuntando a la derecha, +Y apuntando hacia arriba y -Z que señala desde la cámara a través del centro (punto principal) de la imagen. En esa convención, la coordenada Z debe ser negada al dividirse en los componentes X e Y. Por ejemplo:

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 };
}

Se puede lograr un resultado equivalente mediante un vector con cuatro componentes estableciendo el componente Z en 1 y el componente W a la distancia desde la cámara. Tenga en cuenta que los componentes X e Y resultantes deben dividirse por el componente W resultante para producir las coordenadas de píxeles finales:

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 };
}

Si esta transformación se aplicará a muchas coordenadas 3D, puede ser más conveniente ajustar la propia matriz, en lugar de cada coordenada de entrada. Esto se puede lograr intercambiando las terceras y cuartas filas de la matriz y usando una función de transformación de coordenadas homogénea como XMVector3TransformCoordStream. Tenga en cuenta que también se aplica una conversión de derecha a izquierda como parte de la transformación para que la distancia desde la cámara sea un valor positivo:

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 }; });
}

Se aplica a