2016-03-30 19 views
7

Distorting eines Bildes zu einem Viereck scheitern Ich verwende Matrix.setPolyToPoly Funktion, um eine ausgewählte Region (4 Ecken) einer Bitmap in ein Rechteck zu transformieren und normalerweise funktioniert es erstaunlich. Aber im nächsten Beispiel:In einigen Fällen auf Android

4 corners selection image

Die polyToPoly Funktion schlägt die perspektivische Transformation:

Bad transformation image

ich gezeichnet haben zwei Linien für die Prüfung, markieren Sie die Zeilen, in denen ich die vier ausgewählten Punkten wollen .

Was mache ich falsch? Vielen Dank!

EDIT: Ich habe das Problem mit canvas.drawBitmapMesh gelöst haben, Dank pskink für Ihre Beratung !!

Dies ist der letzte Code

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

man kann nicht alles tun mit 'setPolyToPoly', versuchen' Canvas.drawBitmapMesh' statt – pskink

+0

Dank! Ich habe die Frage mit dem endgültigen Code aktualisiert. –

+0

@PepSantacruz Vielen Dank für eine klare, gut ausgedrückte Frage. Der Sinn von SO ist, dass Fragen und Antworten auch nach dem ursprünglichen Beitrag für andere hilfreich sein können. Könnten Sie die Bearbeitung auf Ihre Frage zurücksetzen, so dass der Code dem des ursprünglichen Posts entspricht (mit dem funktionierenden Code in der Antwort, wie Sie es getan haben)? Könnten Sie Ihre Antwort auch "akzeptieren"? Dadurch können künftige Besucher einen klaren Unterschied zwischen dem Code, der ein Problem hatte, und dem Code, der das Problem behoben hat, erkennen. "Akzeptieren" wird einen offensichtlichen Hinweis darauf geben, dass diese Antwort das Problem behoben hat. – Gary99

Antwort

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

danke für die große antwort und frage - schickte eine bounty um danke zu sagen – Fattie

+0

Vielen Dank !! @Fattie –