Transforme um quadro para ser como se tivesse sido tirado de cima usando o OpenCV

Estou trabalhando em um projeto para estimar uma localização de UAV (quadcopter) usando a técnica de fluxo óptico. Atualmente, tenho um código que está usandofarneback algoritmo do OpenCV. O código atual está funcionando bem quando a câmera está sempre apontando para o chão.

Agora, quero adicionar suporte ao gabinete quando a câmera não está apontando diretamente para baixo - o que significa que o quadcopter agora tem um pitch / roll / yaw (ângulos de Euler). Os ângulos de Euler dos quadcopters são conhecidos e estou procurando um método para calcular e aplicar a transformação necessária com base nos ângulos de Euler atuais. Para que a imagem resultante seja como se tivesse sido tirada de cima (veja a imagem abaixo).

Encontrei métodos que calculam a transformação ao ter 2 conjuntos (origem e destino) de 4 cantos viafindHomography ougetPerspectiveTransform funções do OpenCV. Mas não consegui encontrar nenhum método que pudesse fazê-lo sabendo apenas o ângulo de Euler (porque não conheço a imagem de destino correspondente).

Portanto, minha pergunta é: qual método posso usar e como transformar um quadro como se fosse tirado de cima usando apenas ângulos de Euler e altura da câmera do chão, se necessário?

Para demonstrar o que eu preciso:

A parte relevante do meu código atual está abaixo:

for(;;)
{
    Mat m, disp, warp;
    vector<Point2f> corners;
    // take out frame- still distorted
    cap >> origFrame;
    // undistort the frame using the calibration parameters
    cv::undistort(origFrame, undistortFrame, cameraMatrix, distCoeffs, noArray());
    // lower the process effort by transforming the picture to gray
    cvtColor(undistortFrame, gray, COLOR_BGR2GRAY);

    if( !prevgray.empty() )
    {
        // calculate flow
        calcOpticalFlowFarneback(prevgray, gray, uflow, 0.5, 3/*def 3 */, 10/* def 15*/, 3, 3, 1.2 /* def 1.2*/, 0);
        uflow.copyTo(flow);

        // get average
        calcAvgOpticalFlow(flow, 16, corners);

        // calculate range of view - 2*tan(fov/2)*distance
        rovX = 2*0.44523*distanceSonar*100;     // 2 * tan(48/2) * dist(cm)
        rovY = 2*0.32492*distanceSonar*100;     // 2 * tan(36/2) * dist(cm)

        // calculate final x, y location
        location[0] += (currLocation.x/WIDTH_RES)*rovX;
        location[1] += (currLocation.y/HEIGHT_RES)*rovY;
    }
    //break conditions
    if(waitKey(1)>=0)
        break;
    if(end_run)
        break;
    std::swap(prevgray, gray);
}  
ATUALIZAR:

Depois de adicionar a rotação com sucesso, ainda preciso que minha imagem esteja centralizada (e não sair da janela do quadro, como mostrado abaixo). Acho que preciso de algum tipo de tradução.Quero que o centro da imagem de origem esteja no centro da imagem de destino. Como posso adicionar isso também?

A função de rotação que funciona:

void rotateFrame(const Mat &input, Mat &output, Mat &A , double roll, double pitch, double yaw){
    Mat Rx = (Mat_<double>(3, 3) <<
              1,          0,           0,
              0, cos(roll), -sin(roll),
              0, sin(roll),  cos(roll));
    Mat Ry = (Mat_<double>(3, 3) <<
              cos(pitch), 0, sin(pitch),
              0, 1,          0,
              -sin(pitch), 0,  cos(pitch));
    Mat Rz = (Mat_<double>(3, 3) <<
              cos(yaw), -sin(yaw), 0,
              sin(yaw),  cos(yaw), 0,
              0,          0,           1);

    Mat R = Rx*Ry*Rz;
    Mat trans = A*R*A.inv();

    warpPerspective(input, output, trans, input.size());
}

Quando eu corro comrotateFrame(origFrame, processedFrame, cameraMatrix, 0, 0, 0); Recebo a imagem conforme o esperado:

Mas quando eu corro com 10 graus em rolorotateFrame(origFrame, processedFrame, cameraMatrix, 20*(M_PI/180), 0, 0);. A imagem está saindo da janela do quadro:

questionAnswers(3)

yourAnswerToTheQuestion