2012-10-31 11 views
9

Próbuję zrobić transformację perspektywy na bitmapie, którą przechwytuję przez kamerę. Użytkownik dopasowuje kwadrat ograniczający (jak pokazano w białym polu) wokół prostokątnego obiektu. I wtedy próbować przekształcić to do prostokątnego obrazu za pomocą poniższego kodu:Kadrowanie Perspektywicznej transformacji obrazu na Androidzie

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

Jednak mój obraz wynikowy zawiera dane obrazu, który jest poza granicami mojego quada. Byłoby to do przyjęcia, gdybym mógł zrozumieć, jakie są współrzędne kwadratu po transformacji, więc mógłbym przyciąć wynik, ale nie mam absolutnie pojęcia, jak to zrobić.

Każda pomoc będzie bardzo doceniana zarówno po znalezieniu współrzędnych kwadratu po transformacji, jak i najlepiej znaleźć sposób, aby zapobiec tej sytuacji w pierwszej kolejności.

Wejście:

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

wyjściowa:

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

+0

znaleźliście rozwiązanie? Mam ten sam problem. –

+0

@ Romain-guy może masz podpowiedź do tego problemu? –

Odpowiedz

-2

Po utworzeniu nowego Bitmap obraz, można wywołać Android wbudowany w funkcjonalności upraw budując 'uprawy' intencję i nazywając to, na przykład:

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. 

Więcej szczegółów na temat kadrowania obrazu w systemie Android można uzyskać od here.

Należy również dodać następujące w pliku manifestu aplikacji dla tej pracy:

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

miałem ten sam problem i rozwiązać go poprzez znalezienie współrzędne prostokąta po transformacji.

Aby znaleźć te współrzędne, musisz zrozumieć, co się dzieje. Macierz definiuje transformację perspektywy, która jest podawana przez 4 punkty krawędzi quada i odpowiadające im punkty. Zrobiliście to z następującego kodu:

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

Oznacza to (na przykład), że lewy górny punkt swojego quad przekształca się w punkcie (0,0). Możesz to sprawdzić, stosując macierz do punktów i sprawdzając uzyskane wartości. Aby zastosować macierz, możesz użyć metody mapPoints(...). Zdefiniowana macierz transformacji działa dobrze. The (na pierwszy rzut oka) dziwne zachowanie tych wyników transformacji od stworzenia bitmapy:

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

Powstały bitmapy wydaje się być błędne, ponieważ niektóre punkty (na przykład wszystkie punkty na lewo od TOP- lewy punkt kwadratu) są przekształcane na ujemne współrzędne, a jeśli chcesz narysować coś w bitmapie, współrzędne muszą być dodatnie. Z tego powodu transformowane punkty są przesunięte i prowadzą do dziwnych współrzędnych transformowanych punktów w bitmapie.

Podsumowując: Punkty są poprawnie przekształcane na nowe współrzędne, ale nie mogą być wyświetlane iz tego powodu są przesunięte, a przesunięte współrzędne punktów transformowanych w mapie bitowej nie są współrzędnymi zdefiniowanymi w macierz transformacji.

Aby rozwiązać ten problem i uzyskać poprawne współrzędne transformowanych punktów w bitmapie, należy obliczyć wartości przesunięcia. Przesunięcie składa się z wartości x i y.

Aby obliczyć wartość x, przetworzyłem wartość x lewego górnego punktu i wartość x lewego dolnego punktu oryginalnego obrazu z wcześniej zdefiniowaną macierzą. Punkt górny lewy lub dolny lewy jest zamieniany na lewą granicę wynikowej mapy bitowej i dlatego wartość x współrzędnej mapy bitowej tego punktu jest równa 0 i zanegowana (ponieważ x- wartość musi być dodatnia) x-wartość przekształconych współrzędnych jest wartością x zmiany. Punkt, który jest przekształcany na lewą granicę wynikowej bitmapy, jest punktem o maksymalnej zanegowanej wartości x. Dlatego wartość x przesunięcia jest maksymalną z zanegowanych wartości x transformowanego lewego górnego i dolnego lewego punktu.

Aby obliczyć wartość y, przetworzyłem wartość y lewego górnego punktu i wartości y górnego prawego punktu oryginalnego obrazu, ponieważ są to możliwe punkty, które są przekształcane na górę granica wynikowej bitmapy i wartość y transformowanego punktu jest równa 0 w wynikowej bitmapie. Przyjmując ponownie maksimum zanegowanych wartości przekształconych wartości y, otrzymuje się wartość y zmiany.

Otrzymany kod wygląda następująco:

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); 
Powiązane problemy