Compartilhar via


CameraIntrinsics.UndistortedProjectionTransform Propriedade

Definição

Obtém uma matriz que transforma uma coordenada 2D em metros no plano de imagem em coordenadas de pixel de quadro de vídeo sem compensar o modelo de distorção da câmera. O ponto 2D resultante dessa transformação não será mapeado com precisão para a coordenada de pixel em um quadro de vídeo, a menos que o aplicativo aplique sua própria compensação de distorção. Isso é útil para aplicativos que optam por implementar a compensação de distorção baseada em GPU em vez de usar o UndistortPoint, que usa a CPU para calcular a compensação de distorção.

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

Valor da propriedade

Matrix4x4 Matrix4x4

float4x4

Obtém uma matriz que transforma uma coordenada 2D em metros no plano de imagem para as coordenadas de pixel de quadro de vídeo sem compensar o modelo de distorção da câmera.

Requisitos do Windows

Família de dispositivos
Windows 10 Anniversary Edition (introduzida na 10.0.14393.0)
API contract
Windows.Foundation.UniversalApiContract (introduzida na v3.0)

Comentários

A transformação converte de uma coordenada 2D em metros no plano de imagem (origem no ponto principal, +X apontando para a direita e +Y apontando para cima), para uma coordenada 2D em pixels com a origem no canto superior esquerdo da imagem e +X apontando para a direita e +Y apontando para baixo. Se a coordenada 2D for expressa como um vetor com quatro componentes, Z deverá ser definido como 0 e W deverá definir como 1.

Para converter uma coordenada 3D no sistema de coordenadas da câmera em coordenadas de pixel, os componentes X e Y da coordenada devem primeiro ser divididos pela distância da câmera (ou seja, a coordenada Z) para projetá-los no plano de imagem. Observe que os sistemas de coordenadas da câmera são destros por convenção, com +X apontando para a direita, +Y apontando para cima e -Z apontando da câmera pelo centro (ponto principal) da imagem. Nessa convenção, a coordenada Z deve ser negada ao se dividir nos componentes X e Y. Por exemplo:

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

Um resultado equivalente pode ser obtido usando um vetor com quatro componentes definindo o componente Z como 1 e o componente W para a distância da câmera. Observe que os componentes X e Y resultantes devem ser divididos pelo componente W resultante para produzir as coordenadas de pixel finais:

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

Se essa transformação for aplicada a muitas coordenadas 3D, talvez seja mais conveniente ajustar a própria matriz, em vez de cada coordenada de entrada. Isso pode ser feito trocando a terceira e a quarta linhas da matriz e usando uma função de transformação de coordenada homogênea como XMVector3TransformCoordStream. Observe que uma conversão de mão direita para a esquerda também é aplicada como parte da transformação para que a distância da câmera seja um 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 }; });
}

Aplica-se a