다음을 통해 공유


CameraIntrinsics.UndistortedProjectionTransform 속성

정의

카메라의 왜곡 모델에 대한 보상 없이 이미지 평면의 미터 단위로 2D 좌표를 비디오 프레임 픽셀 좌표로 변환하는 행렬을 가져옵니다. 이 변환으로 인한 2D 지점은 앱이 자체 왜곡 보정을 적용하지 않는 한 비디오 프레임의 픽셀 좌표에 정확하게 매핑되지 않습니다. 이는 CPU를 사용하여 왜곡 보정을 계산하는 데 사용하는 UndistortPoint를 사용하는 대신 GPU 기반 왜곡 보정을 구현하도록 선택하는 앱에 유용합니다.

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 좌표가 4개의 구성 요소가 있는 벡터로 표현되는 경우 Z를 0으로 설정하고 W를 1로 설정해야 합니다.

카메라 좌표계의 3D 좌표를 픽셀 좌표로 변환하려면 먼저 좌표의 X 및 Y 구성 요소를 카메라(예: Z 좌표)의 거리로 나누어 이미지 평면에 프로젝션해야 합니다. 카메라 좌표계는 +X가 오른쪽을 가리키고 , +Y가 가리키고, -Z가 이미지의 중심(주 지점)을 통해 카메라에서 가리키는 규칙에 따라 오른손으로 지정됩니다. 이 규칙에서 X 및 Y 구성 요소로 나눌 때 Z 좌표를 부정해야 합니다. 예를 들면 다음과 같습니다.

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 구성 요소를 카메라와의 거리로 설정하여 4개의 구성 요소가 있는 벡터를 사용하여 동등한 결과를 달성할 수 있습니다. 최종 픽셀 좌표를 생성하려면 결과 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 }; });
}

적용 대상