Transforme un marco para que sea como si hubiera sido tomado desde arriba usando OpenCV

Estoy trabajando en un proyecto para estimar la ubicación de un UAV (quadcopter) utilizando la técnica de flujo óptico. Actualmente tengo un código que está usandofarneback algoritmo de OpenCV. El código actual funciona bien cuando la cámara siempre apunta al suelo.

Ahora, quiero agregar soporte a la carcasa cuando la cámara no apunta hacia abajo, lo que significa que el cuadricóptero ahora tiene una inclinación / balanceo / guiñada (ángulos de Euler). Los ángulos de Euler de los cuadricópteros son conocidos y estoy buscando un método para calcular y aplicar la transformación necesaria basada en los ángulos de Euler actuales conocidos. Para que la imagen resultante sea como si se hubiera tomado desde arriba (ver imagen a continuación).

Encontré métodos que calculan la transformación cuando se tienen 2 conjuntos (origen y destino) de 4 esquinas a través defindHomography ogetPerspectiveTransform funciones de OpenCV. Pero no pude encontrar ningún método que pueda hacerlo con solo conocer el ángulo de Euler (porque no conozco los núcleos de imágenes de destino).

Entonces, mi pregunta es ¿qué método puedo usar y cómo para transformar un cuadro para que se tome desde arriba usando solo los ángulos de Euler y la altura de la cámara desde el suelo si es necesario?

Para demostrar lo que necesito:

La parte relevante de mi código actual está a continuación:

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

Después de agregar con éxito la rotación, todavía necesito que mi imagen esté centrada (y no salir de la ventana del marco como se muestra a continuación). Supongo que necesito algún tipo de traducción.Quiero que el centro de la imagen de origen esté en el centro de la imagen de destino. ¿Cómo puedo agregar esto también?

La función de rotación 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());
}

Cuando lo ejecuto conrotateFrame(origFrame, processedFrame, cameraMatrix, 0, 0, 0); Me sale la imagen como se esperaba:

Pero cuando lo corro con 10 grados en rollorotateFrame(origFrame, processedFrame, cameraMatrix, 20*(M_PI/180), 0, 0);. La imagen sale de la ventana del marco:

Respuestas a la pregunta(3)

Su respuesta a la pregunta