在Android上裁剪图像的透视变换 [英] Cropping a Perspective Transformation of Image on Android

查看:151
本文介绍了在Android上裁剪图像的透视变换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试对通过相机捕获的位图进行透视变换.用户围绕矩形对象调整边界四边形(如白框所示).然后,我尝试使用以下代码将其转换为矩形图像:

I'm trying to do a perspective transform on a bitmap that I capture via the camera. The user adjusts a bounding quad (as depicted by the white box) around a rectangular object. I then attempt to transform this to a rectangular image using the code below:

public static Bitmap perspectiveTransformation(Bitmap bitmap,BoundingQuad boundingQuad)
{
    Matrix matrix = new Matrix();
    float[] dst = new float[] {
            0,
            0,
            bitmap.getWidth(),
            0,
            bitmap.getWidth(),
            bitmap.getHeight(),
            0,
            bitmap.getHeight()
    };
    float[] src = new float[] {
            boundingQuad.topLeft.x,
            boundingQuad.topLeft.y,
            boundingQuad.topRight.x,
            boundingQuad.topRight.y,
            boundingQuad.bottomRight.x,
            boundingQuad.bottomRight.y,
            boundingQuad.bottomLeft.x,
            boundingQuad.bottomLeft.y
    };
    matrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1);
    return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}

但是,我得到的图像包含的图像数据不在四边形的边界范围内.如果我能弄清楚变换后四边形的坐标是什么,那么我可以裁剪结果,但是我绝对不知道该怎么做.

However my resulting image contains image data that is outside the boundary of my quad. This would be acceptable if I could figure out what the coordinates of the quad are after transformation so I could crop the result but I have absolutely no idea how to do that.

在变换后找到四边形的坐标,或者理想情况下找到一种方法来防止这种情况首先发生的任何帮助,将不胜感激.

Any help would be greatly appreciated in either finding the coordinates of the quad after transformation or ideally finding a way to prevent this situation from occurring in the first place.

输入:

http://i.stack.imgur.com/33RfN.png

输出:

http://i.stack.imgur.com/zWFvA.png

推荐答案

我遇到了同样的问题,并通过在转换后找到矩形的坐标来解决了这个问题.

I had the same problem and solved it by finding the coordinates of the rectangle after the transformation.

要找到这些坐标,您必须了解发生了什么. 矩阵定义了透视变换,该变换由四边形的4个边缘点和相应的点给出.您已使用以下代码完成了此操作:

To find these coordinates you have to understand what's going on. The matrix defines a perspective transformation, which is given by the 4 edge-points of the quad and the corresponding points. You have done this with the following code:

Matrix matrix = new Matrix();
float[] dst = new float[] {
        0,
        0,
        bitmap.getWidth(),
        0,
        bitmap.getWidth(),
        bitmap.getHeight(),
        0,
        bitmap.getHeight()
};
float[] src = new float[] {
        boundingQuad.topLeft.x,
        boundingQuad.topLeft.y,
        boundingQuad.topRight.x,
        boundingQuad.topRight.y,
        boundingQuad.bottomRight.x,
        boundingQuad.bottomRight.y,
        boundingQuad.bottomLeft.x,
        boundingQuad.bottomLeft.y
}; 
matrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1);

(例如)这意味着四边形的左上角点将转换为点(0,0).您可以通过将矩阵应用于点并检查结果值来验证这一点.要应用矩阵,可以使用方法mapPoints(...).定义的转换矩阵可以正常工作.乍看之下,这种转换的奇怪行为是由位图的创建引起的:

This means (for example) that the top-left point of your quad is transformed to the point (0,0). You can verify this by applying the matrix to the points and check the resulting values. To apply the matrix you can use the method mapPoints(...). The defined transformation-matrix works fine. The (at the first look) strange behavior of this transformation results from the creation of the bitmap:

    return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);

最终的位图似乎是错误的,因为某些点(例如,四边形左上角点的所有点都被转换为负坐标),并且如果您想在位图中绘制某些内容,则坐标为要积极.因此,变换后的点会发生位移,从而导致位图中变换后的点的坐标奇怪.

The resulting bitmap seems to be wrong, because some points (for example all points to the left of the top-left point of the quad) are transformed to negative coordinates and if you want to draw something into a bitmap the coordinates have to be positive. Because of this the transformed points are shift and that leads to strange coordinates of the transformed points in the bitmap.

得出结论:点已正确转换为新坐标,但无法显示,因此,它们已移动并且位图中转换后的点的已移动坐标不是在转换中定义的坐标-矩阵.

To conclude: The points are transformed correctly to the new coordinates, but can not be displayed and because of this they are shifted and the shifted coordinates of the transformed points in the bitmap are not the coordinates, which are defined in the transformation-matrix.

要解决此问题并获取位图中变换点的正确坐标,您必须计算shift的值.移位由x值和y值组成.

To solve this problem and get the proper coordinates of the transformed points in the bitmap, you have to calculate the values of the shift. The shift consists of a x-value and a y-value.

为了计算x值,我使用预先定义的矩阵转换了原始图像的左上角点的x值和左下角点的x值.左上角点或左下角点将转换为结果位图的左边界,因此,该点的位图坐标的x值等于0且为负(因为x-值必须为正).转换后的坐标的x值是平移的x值.转换到结果位图左边界的点是x值最大为负的点.因此,平移的x值是转换后的左上和左下点的x值的最大值.

To calculate the x-value I transformed the x-value of the top-left point and the x-value of the lower-left point of the original image with the previously defined matrix. Either the top-left point or the lower-left point is transformed to the left boundary of the resulting bitmap and because of this the x-value of the bitmap-coordinate of this point is equal to 0 and the negated (because the x-value needs to be positive) x-value of the transformed coordinates is the x-value of the shift. The point, which is transformed to the left boundary of the resulting bitmap is the point with the maximal negated x-value. Therefore the x-value of the shift is the maximum of the negated x-values of the transformed top-left and lower-left point.

为了计算y值,我对原始图像的左上角点的y值和右上角点的y值进行了转换,因为这是可能的点,它们已转换为顶部边界生成的位图的,并且转换后的点的y值在生成的位图中等于0.通过再次获取转换后的y值的负值的最大值,您将获得平移的y值.

To calculate the y-value I transformed the y-value of the top-left point and the y-value of the top-right point of the original image, because this are the possible points which are transformed to the top boundary of the resulting bitmap and the y-value of the transformed point is equal to 0 in the resulting bitmap. By taking again the maximum of the negated values of the transformed y-values, you get the y-value of the shift.

结果代码如下:

    float[] mappedTL = new float[] { 0, 0 };
    matrix.mapPoints(mappedTL);
    int maptlx = Math.round(mappedTL[0]);
    int maptly = Math.round(mappedTL[1]);

    float[] mappedTR = new float[] { bitmap.getWidth(), 0 };
    matrix.mapPoints(mappedTR);
    int maptrx = Math.round(mappedTR[0]);
    int maptry = Math.round(mappedTR[1]);

    float[] mappedLL = new float[] { 0, bitmap.getHeight() };
    matrix.mapPoints(mappedLL);
    int mapllx = Math.round(mappedLL[0]);
    int maplly = Math.round(mappedLL[1]);

    int shiftX = Math.max(-maptlx, -mapllx);
    int shiftY = Math.max(-maptry, -maptly);

    Bitmap resultBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    return Bitmap.createBitmap(resultBitmap, shiftX, shiftY, bitmap.getWidth(), bitmap.getHeight(), null, true);

这篇关于在Android上裁剪图像的透视变换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆