Cálculo de la relación de aspecto de la imagen de destino Transformar perspectiva

Recientemente he implementadoTransformación de perspectiva enOpenCV a mi aplicación enAndroide. Casi todo funciona sin problemas, pero un aspecto necesita mucho más trabajo por hacer.

El problema es que no sé cómo contar la relación de aspecto correcta de la imagen de destino de Transformación de perspectiva (no tiene que establecerse manualmente), por lo que podría contar la relación de aspecto de la imagen con el tamaño de la imagen real. cosa / imagena pesar del ángulo de una cámara. Tenga en cuenta que las coordenadas iniciales no forman un trapecio, sí forma un cuadrángulo.

Si tengo una fotografía de un libro tomada desde aproximadamente 45 grados y quiero que la relación de aspecto de la imagen de destino sea más o menos la misma que la relación de aspecto de este libro. Es difícil tener una foto 2D, peroCamScanner La aplicación lo hace perfectamente. He hecho una forma muy simple de contar el tamaño de mi imagen de destino (sin expectativas de que funcione como quiero), pero hace que la imagen desde un ángulo de 45 grados sea aproximadamente un 20% más corta y al bajar el ángulo la altura de la imagen se reduce significativamente, mientras que CamScanner lo hace perfectamente a pesar del ángulo:

Aquí, CamScanner mantiene la relación de aspecto de la imagen de destino (la segunda) igual que la del libro, lo hizo con bastante precisión incluso a un ángulo de ~ 20 grados.

Mientras tanto, mi código se ve así (mientras cuento los tamaños de la imagen de destino, no tengo intención de que funcione como hago en esta pregunta):

public static Mat PerspectiveTransform(Point[] cropCoordinates, float ratioW, float ratioH, Bitmap croppedImage)
{
    if (cropCoordinates.length != 4) return null;

    double width1, width2, height1, height2, avgw, avgh;
    Mat src = new Mat();
    List<Point> startCoords = new ArrayList<>();
    List<Point> resultCoords = new ArrayList<>();

    Utils.bitmapToMat(croppedImage, src);

    for (int i = 0; i < 4; i++)
    {
        if (cropCoordinates[i].y < 0 ) new Point(cropCoordinates[i].x, 0);
        startCoords.add(new Point(cropCoordinates[i].x * ratioW, cropCoordinates[i].y * ratioH));
    }

    width1 = Math.sqrt(Math.pow(startCoords.get(2).x - startCoords.get(3).x,2) + Math.pow(startCoords.get(2).y - startCoords.get(3).y,2));
    width2 = Math.sqrt(Math.pow(startCoords.get(1).x - startCoords.get(0).x,2) + Math.pow(startCoords.get(1).y - startCoords.get(0).y,2));
    height1 = Math.sqrt(Math.pow(startCoords.get(1).x - startCoords.get(2).x, 2) + Math.pow(startCoords.get(1).y - startCoords.get(2).y, 2));
    height2 = Math.sqrt(Math.pow(startCoords.get(0).x - startCoords.get(3).x, 2) + Math.pow(startCoords.get(0).y - startCoords.get(3).y, 2));
    avgw = (width1 + width2) / 2;
    avgh = (height1 + height2) / 2;

    resultCoords.add(new Point(0, 0));
    resultCoords.add(new Point(avgw-1, 0));
    resultCoords.add(new Point(avgw-1, avgh-1));
    resultCoords.add(new Point(0, avgh-1));

    Mat start = Converters.vector_Point2f_to_Mat(startCoords);
    Mat result = Converters.vector_Point2d_to_Mat(resultCoords);
    start.convertTo(start, CvType.CV_32FC2);
    result.convertTo(result,CvType.CV_32FC2);

    Mat mat = new Mat();
    Mat perspective = Imgproc.getPerspectiveTransform(start, result);
    Imgproc.warpPerspective(src, mat, perspective, new Size(avgw, avgh));

    return mat;
}

Y desde relativamente el mismo ángulo, mi método produce este resultado:

Lo que quiero saber es cómo es posible hacerlo. Es interesante para mí cómo lograron contar la longitud del objeto simplemente teniendo coordenadas de 4 esquinas. Además, si es posible, proporcione algunas explicaciones de código / matemáticas o artículos similares / similares.

Gracias de antemano.

Respuestas a la pregunta(2)

Su respuesta a la pregunta