2012-10-31 3 views
9

Sto provando a eseguire una trasformazione prospettica su una bitmap che acquisisco tramite la fotocamera. L'utente regola un quadrante di delimitazione (come illustrato dalla casella bianca) attorno a un oggetto rettangolare. Ho quindi tentare di trasformare questo a un'immagine rettangolare usando il codice seguente:Ritaglio di una prospettiva Trasformazione dell'immagine su Android

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); 
} 

Tuttavia la mia immagine risultante contiene dati di immagine che è al di fuori del confine del mio quad. Questo sarebbe accettabile se riuscissi a capire quali sono le coordinate del quad dopo la trasformazione in modo da poter ritagliare il risultato ma non ho assolutamente idea di come farlo.

Qualsiasi aiuto sarebbe molto apprezzato sia nel trovare le coordinate del quad dopo la trasformazione o trovare idealmente un modo per evitare che questa situazione si verifichi in primo luogo.

ingresso:

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

uscita:

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

+0

hai trovato una soluzione? Ho lo stesso problema. –

+0

@ romain-guy forse hai un suggerimento su questo problema? –

risposta

-2

Dopo aver creato la nuova immagine Bitmap, è possibile chiamare Android costruito in funzione delle colture con la costruzione di un intento 'raccolto' e chiamandolo, esempio:

Intent cropIntent = new Intent("com.android.camera.action.CROP"); 

// Put in 'Extras' here to build the intent 

// Start the activity. It will be handled by returning data to onActivityResult 
startActivityForResult(cropIntent, PIC_CROP); // PIC_CROP is just an arbitrary tag name. 

Ulteriori dettagli sul ritaglio di immagini in Android possono essere ottenuti da here.

Sarà inoltre necessario aggiungere quanto segue nel file manifesto della tua app per far funzionare tutto questo:

<uses-feature android:name="android.hardware.camera" ></uses-feature> 
<uses-permission android:name="android.permission.CAMERA" /> 
3

Ho avuto lo stesso problema e risolto trovando le coordinate del rettangolo dopo la trasformazione.

Per trovare queste coordinate devi capire cosa sta succedendo. La matrice definisce una trasformazione prospettica, che è data dai 4 punti di bordo del quadrato e dai punti corrispondenti. Avete fatto questo con il seguente codice:

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); 

Questo significa (per esempio) che il punto in alto a sinistra del vostro quad è trasformato al punto (0,0). Puoi verificarlo applicando la matrice ai punti e verificando i valori risultanti. Per applicare la matrice è possibile utilizzare il metodo mapPoints(...). La matrice di trasformazione definita funziona correttamente. L'(al primo sguardo) strano comportamento di questa trasformazione risultati dalla creazione della bitmap:

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

La bitmap risultante sembra essere sbagliato, perché alcuni punti (ad esempio tutti i punti a sinistra del top- punto di sinistra del quadrante) vengono trasformati in coordinate negative e se si desidera disegnare qualcosa in una bitmap le coordinate devono essere positive. Per questo motivo i punti trasformati sono spostati e questo porta a coordinate strane dei punti trasformati nella bitmap.

Per concludere: i punti vengono trasformati correttamente alle nuove coordinate, ma non possono essere visualizzati e per questo vengono spostati e le coordinate spostate dei punti trasformati nella bitmap non sono le coordinate, che sono definite nel trasformazione-matrice.

Per risolvere questo problema e ottenere le coordinate corrette dei punti trasformati nella bitmap, è necessario calcolare i valori dello spostamento. Lo spostamento consiste in un valore x e un valore y.

Per calcolare il valore x ho trasformato il valore x del punto in alto a sinistra e il valore x del punto in basso a sinistra dell'immagine originale con la matrice precedentemente definita. O il punto in alto a sinistra o il punto in basso a sinistra viene trasformato al limite sinistro della bitmap risultante e per questo il valore x della coordinata bitmap di questo punto è uguale a 0 e il negativo (perché la x- il valore deve essere positivo) Il valore x delle coordinate trasformate è il valore x dello spostamento. Il punto, che viene trasformato al limite sinistro della bitmap risultante, è il punto con il valore x massimo negato. Pertanto il valore x dello spostamento è il massimo dei valori x negati del punto trasformato in alto a sinistra e in basso a sinistra.

Per calcolare il valore y ho trasformato il valore y del punto in alto a sinistra e il valore y del punto in alto a destra dell'immagine originale, perché questi sono i possibili punti che vengono trasformati in cima il limite della bitmap risultante e il valore y del punto trasformato è uguale a 0 nella bitmap risultante. Riprendendo il massimo dei valori negativi dei valori y trasformati, ottieni il valore y dello spostamento.

Il codice risultante è simile al seguente:

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);