2016-03-30 26 views
7

Sto utilizzando la funzione matrix.setPolyToPoly per trasformare una regione selezionata (4 angoli) di una bitmap in un rettangolo e normalmente funziona in modo sorprendente. Ma nel prossimo esempio:In alcuni casi la distorsione di un'immagine in un quadrilatero non funziona su Android

4 corners selection image

La funzione polyToPoly fallisce la prospettiva trasformano:

Bad transformation image

ho disegnato due linee per i test, le linee di Mark dove voglio i quattro punti selezionati .

Cosa sto facendo male? Grazie!

EDIT: Ho risolto il problema utilizzando canvas.drawBitmapMesh, grazie pskink per il vostro consiglio !!

Questo è il codice finale

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; 
} 
+1

non si può fare tutto con 'setPolyToPoly', provare' Canvas.drawBitmapMesh' invece – pskink

+0

Grazie! Ho aggiornato la domanda con il codice finale. –

+0

@PepSantacruz Grazie per una domanda chiara e ben espressa. Lo spirito di SO è che domande e risposte possono essere utili agli altri molto tempo dopo il post originale. È questo lo spirito, potresti ripristinare la modifica alla tua domanda in modo che il codice sia quello del post originale (con il codice funzionante nella risposta come hai fatto tu)? Inoltre, potresti "accettare" la tua risposta. Facendo queste cose, i futuri visitatori saranno in grado di vedere una chiara differenza tra il codice che ha avuto un problema e il codice che ha risolto il problema. 'Accetta' farà un'indicazione evidente che questa risposta ha risolto il problema. – Gary99

risposta

1
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; 
} 
+0

grazie per l'ottima risposta e la domanda - inviato una taglia per dire grazie – Fattie

+0

Grazie !! @Fattie –