将2D屏幕坐标转换为3D世界坐标

时间:2018-01-03 12:52:50

标签: c++ 3d directx

现在我可以将3D世界坐标转换为2D屏幕坐标。 我可以用这个来实现:

    D3DXMATRIX viewMatrix = renderer->viewMatrix;
    D3DXMATRIX projectionMatrix = renderer->projectionMatrix;
    D3DXMATRIX viewProjectionMatrix = D3DXMATRIX();
    D3DXMatrixMultiply(&viewProjectionMatrix, &viewMatrix, &projectionMatrix);

    D3DXVECTOR3 pScreen = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 pWorld(world->getX(), world->getY(), world->getZ());
    D3DXVec3TransformCoordImpl(&pScreen, &pWorld, &viewProjectionMatrix);

现在pScreen包含2D屏幕坐标

我怎样才能将其反转以从2D屏幕坐标中获取3D世界坐标?我正在使用D3DXVec3TransformCoord函数的这种实现:

D3DXVECTOR3* WINAPI D3DXVec3TransformCoordImpl(D3DXVECTOR3* pout, CONST D3DXVECTOR3* pv, CONST D3DXMATRIX* pm)
{
    FLOAT norm = pm->m[0][3] * pv->x + pm->m[1][3] * pv->y + pm->m[2][3] * pv->z + pm->m[3][3];
    if (norm)
    {
        pout->x = (pm->m[0][0] * pv->x + pm->m[1][0] * pv->y + pm->m[2][0] * pv->z + pm->m[3][0]) / norm;
        pout->y = (pm->m[0][1] * pv->x + pm->m[1][1] * pv->y + pm->m[2][1] * pv->z + pm->m[3][1]) / norm;
        pout->z = (pm->m[0][2] * pv->x + pm->m[1][2] * pv->y + pm->m[2][2] * pv->z + pm->m[3][2]) / norm;
    }
    else
    {
        pout->x = 0.0f;
        pout->y = 0.0f;
        pout->z = 0.0f;
    }
    return pout;
}

1 个答案:

答案 0 :(得分:0)

您可以像这样使用SolvePnP库:

int max = std::max(img.rows,img.cols);
Mat camMatrix = (Mat_<double>(3,3) <<
    max_d,   0, img.cols/2.0,
    0,   max_d, img.rows/2.0,
    0,   0,     1.0);

// 2d -> 3d correspondence
vector<Point2d> pts2d = ...
vector<Point3d> pts3d = ...
Mat rvec,tvec;
solvePnP(pts3d, pts2d, camMatrix, Mat(1,4,CV_64F,0.0), rvec, tvec, false, SOLVEPNP_EPNP);
// get 3d rot mat
Mat rotM(3, 3, CV_64F);
Rodrigues(rvec, rotM);

// push tvec to transposed Mat
Mat rotMT = rotM.t();
rotMT.push_back(tvec.reshape(1, 1));

// transpose back, and multiply
camMatrix * rotMT.t();