android - 在 Android 上的某些情况下,将图像扭曲成四边形会失败

标签 android matrix android-bitmap perspective

我正在使用 matrix.setPolyToPoly 函数将位图的选定区域(4 个角)转换为矩形,通常效果非常好。但在下一个例子中:

4 corners selection image

polyToPoly 函数无法进行透视变换:

Bad transformation image

我画了两条线用于测试,线标记了我想要四个选定点的位置。

我做错了什么?谢谢!

编辑:我已经使用 canvas.drawBitmapMesh 解决了这个问题,谢谢 pskink征求您的意见!!

这是最终代码

private float[] generateVertices(int widthBitmap, int heightBitmap) {
    float[] vertices=new float[(WIDTH_BLOCK+1)*(HEIGHT_BLOCK+1)*2];

    float widthBlock = (float)widthBitmap/WIDTH_BLOCK;
    float heightBlock = (float)heightBitmap/HEIGHT_BLOCK;

    for(int i=0;i<=HEIGHT_BLOCK;i++)
        for(int j=0;j<=WIDTH_BLOCK;j++) {
            vertices[i * ((HEIGHT_BLOCK+1)*2) + (j*2)] = j * widthBlock;
            vertices[i * ((HEIGHT_BLOCK+1)*2) + (j*2)+1] = i * heightBlock;
        }
    return vertices;
}

private Bitmap perspectiveTransformation(Bitmap bitmap, ArrayList<Point> bitmapPoints) {

    Bitmap correctedBitmap;
    int maxX = (int) Math.max(Math.abs(bitmapPoints.get(0).x - bitmapPoints.get(1).x), Math.abs(bitmapPoints.get(2).x - bitmapPoints.get(3).x));
    int maxY = (int) Math.max(Math.abs(bitmapPoints.get(0).y - bitmapPoints.get(3).y), Math.abs(bitmapPoints.get(1).y - bitmapPoints.get(2).y));
    Log.d("max", "x=" + maxX + " y=" + maxY); //This is the desired final size

    Bitmap.Config conf = Bitmap.Config.ARGB_8888;
    correctedBitmap = Bitmap.createBitmap(maxX,maxY,conf); //the final bitmap
    float mVertices[] =generateVertices(bitmap.getWidth(),bitmap.getHeight());

    Point mLeftTop = bitmapPoints.get(0);
    Point mRightTop = bitmapPoints.get(1);
    Point mLeftBot = bitmapPoints.get(3);
    Point mRightBot = bitmapPoints.get(2);  //the points on the image where the user has clicked

    Canvas canvas = new Canvas(correctedBitmap);

    Matrix matrix = new Matrix();
    matrix.setPolyToPoly(
            new float[]{mLeftTop.x, mLeftTop.y,
                    mRightTop.x, mRightTop.y,
                    mRightBot.x, mRightBot.y,
                    mLeftBot.x, mLeftBot.y   //the user's points
            },
            0,
            new float[]{0, 0,
                    maxX - 1, 0,
                    maxX - 1, maxY - 1,
                    0, maxY - 1             //where I want the user points in the corrected image
            }
            , 0, 4);

    canvas.concat(matrix);

    Paint paint = new Paint();
    paint.setAntiAlias(true);       //testing parameters
    paint.setFilterBitmap(true);    //testing parameters

    paint.setColor(Color.BLUE);
    paint.setStyle(Paint.Style.STROKE);

    canvas.drawBitmapMesh(bitmap, WIDTH_BLOCK , HEIGHT_BLOCK, mVertices,0,null,0, paint);  //draw the original bitmap into the corrected bitmap with PolyToPoly transformation matrix

    canvas.drawLine(mLeftTop.x, mLeftTop.y, mRightBot.x, mRightBot.y, paint); //draw two lines for testing the transformation matrix
    canvas.drawLine(mLeftBot.x, mLeftBot.y, mRightTop.x, mRightTop.y, paint);

    //bitmap.recycle();  //just testing

    return correctedBitmap;
}

最佳答案

private float[] generateVertices(int widthBitmap, int heightBitmap) {
    float[] vertices=new float[(WIDTH_BLOCK+1)*(HEIGHT_BLOCK+1)*2];

    float widthBlock = (float)widthBitmap/WIDTH_BLOCK;
    float heightBlock = (float)heightBitmap/HEIGHT_BLOCK;

    for(int i=0;i<=HEIGHT_BLOCK;i++)
        for(int j=0;j<=WIDTH_BLOCK;j++) {
            vertices[i * ((HEIGHT_BLOCK+1)*2) + (j*2)] = j * widthBlock;
            vertices[i * ((HEIGHT_BLOCK+1)*2) + (j*2)+1] = i * heightBlock;
        }
    return vertices;
}

private Bitmap perspectiveTransformation(Bitmap bitmap, ArrayList<Point> bitmapPoints) {

    Bitmap correctedBitmap;
    int maxX = (int) Math.max(Math.abs(bitmapPoints.get(0).x - bitmapPoints.get(1).x), Math.abs(bitmapPoints.get(2).x - bitmapPoints.get(3).x));
    int maxY = (int) Math.max(Math.abs(bitmapPoints.get(0).y - bitmapPoints.get(3).y), Math.abs(bitmapPoints.get(1).y - bitmapPoints.get(2).y));
    Log.d("max", "x=" + maxX + " y=" + maxY); //This is the desired final size

    Bitmap.Config conf = Bitmap.Config.ARGB_8888;
    correctedBitmap = Bitmap.createBitmap(maxX,maxY,conf); //the final bitmap
    float mVertices[] =generateVertices(bitmap.getWidth(),bitmap.getHeight());

    Point mLeftTop = bitmapPoints.get(0);
    Point mRightTop = bitmapPoints.get(1);
    Point mLeftBot = bitmapPoints.get(3);
    Point mRightBot = bitmapPoints.get(2);  //the points on the image where the user has clicked

    Canvas canvas = new Canvas(correctedBitmap);

    Matrix matrix = new Matrix();
    matrix.setPolyToPoly(
            new float[]{mLeftTop.x, mLeftTop.y,
                    mRightTop.x, mRightTop.y,
                    mRightBot.x, mRightBot.y,
                    mLeftBot.x, mLeftBot.y   //the user's points
            },
            0,
            new float[]{0, 0,
                    maxX - 1, 0,
                    maxX - 1, maxY - 1,
                    0, maxY - 1             //where I want the user points in the corrected image
            }
            , 0, 4);

    canvas.concat(matrix);

    Paint paint = new Paint();
    paint.setAntiAlias(true);       //testing parameters
    paint.setFilterBitmap(true);    //testing parameters

    paint.setColor(Color.BLUE);
    paint.setStyle(Paint.Style.STROKE);

    canvas.drawBitmapMesh(bitmap, WIDTH_BLOCK , HEIGHT_BLOCK, mVertices,0,null,0, paint);  //draw the original bitmap into the corrected bitmap with PolyToPoly transformation matrix

    canvas.drawLine(mLeftTop.x, mLeftTop.y, mRightBot.x, mRightBot.y, paint); //draw two lines for testing the transformation matrix
    canvas.drawLine(mLeftBot.x, mLeftBot.y, mRightTop.x, mRightTop.y, paint);

    //bitmap.recycle();  //just testing

    return correctedBitmap;
}

关于android - 在 Android 上的某些情况下,将图像扭曲成四边形会失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36308856/

相关文章:

android - 应用内结算到期

java - OpenGL ES 3.0 中的粒子系统优化

arrays - 更改稀疏矩阵某些列中的非零值

reshape 相关矩阵以按列对堆叠

android - 有没有办法在不将其保存到 sdcard 的情况下获取位图的 URI?

android - 在没有 Apache HTTP 客户端的情况下从流中解码位图

android - 1 个应用程序处理所有 NFC 请求,还是很多应用程序?

java - 无法实例化服务 - Java.NullPointerException

r - 我怎样才能使矩阵和向量的处理规则化(例如,在 Matlab 中)

android - 如何在 Glide 的帮助下将 Arraylist<Bitmap> 作为输出?