2013-06-28 29 views
5

Z trudem wdrażam system quad-quad w mojej aplikacji na Androida. Celem jest umożliwienie użytkownikowi zrobienia zdjęcia, dodanie 4 punktów narożnych i wyjęcie tego kwadratu z obrazu jako prostokąta.Nie można uzyskać rozwiązania warpPerspective OpenCV do pracy na Androidzie

Spojrzałem na this method i this question, aby użyć OpenCV do tego. Otrzymany kod jest taka:

public static Bitmap warp(Bitmap image, MyPoint p1, MyPoint p2, MyPoint p3, MyPoint p4) { 
    int resultWidth = 500; 
    int resultHeight = 500; 

    Mat inputMat = new Mat(image.getHeight(), image.getHeight(), CvType.CV_8UC4); 
    Utils.bitmapToMat(image, inputMat); 
    Mat outputMat = new Mat(resultWidth, resultHeight, CvType.CV_8UC4); 

    Point ocvPIn1 = new Point(p1.getX(), p1.getY()); 
    Point ocvPIn2 = new Point(p2.getX(), p2.getY()); 
    Point ocvPIn3 = new Point(p3.getX(), p3.getY()); 
    Point ocvPIn4 = new Point(p4.getX(), p4.getY()); 
    List<Point> source = new ArrayList<Point>(); 
    source.add(ocvPIn1); 
    source.add(ocvPIn2); 
    source.add(ocvPIn3); 
    source.add(ocvPIn4); 
    Mat startM = Converters.vector_Point2f_to_Mat(source); 

    Point ocvPOut1 = new Point(0, 0); 
    Point ocvPOut2 = new Point(0, resultHeight); 
    Point ocvPOut3 = new Point(resultWidth, resultHeight); 
    Point ocvPOut4 = new Point(resultWidth, 0); 
    List<Point> dest = new ArrayList<Point>(); 
    dest.add(ocvPOut1); 
    dest.add(ocvPOut2); 
    dest.add(ocvPOut3); 
    dest.add(ocvPOut4); 
    Mat endM = Converters.vector_Point2f_to_Mat(dest);  

    Mat perspectiveTransform = new Mat(3, 3, CvType.CV_32FC1); 
    Core.perspectiveTransform(startM, endM, perspectiveTransform); 

    Imgproc.warpPerspective(inputMat, 
          outputMat, 
          perspectiveTransform, 
          new Size(resultWidth, resultHeight), 
          Imgproc.INTER_CUBIC); 

    Bitmap output = Bitmap.createBitmap(resultWidth, resultHeight, Bitmap.Config.RGB_565); 
    Utils.matToBitmap(outputMat, output); 
    return output; 
} 

Podczas testowania, I upewnij się, że kolejność punktów narożnych jest top-lewy, dolny-lewy, dolny prawy, górny prawy.

Dziwne jest to, że wynik nie zawsze jest taki sam. W większości przypadków pokazuje kwadrat o jednym kolorze, czasem czarny kwadrat, czasami przekątna z różnymi kolorami. Nawet eksperymentowanie z startM = endM powoduje zachowanie niedeterministyczne.

Czego mi tu brakuje?

+0

to działa jak, ale czasami daje m irror i/lub obrócona kopia końcowej bitmapy. ? czy to jest pożądane? –

Odpowiedz

5

Znaleziono go, problem był w tych wierszach:

Mat perspectiveTransform = new Mat(3, 3, CvType.CV_32FC1); 
Core.perspectiveTransform(startM, endM, perspectiveTransform); 

które powinny zostać zastąpione niniejszym:

Mat perspectiveTransform = Imgproc.getPerspectiveTransform(startM, endM); 
+1

Dzięki @Aegoins u zaoszczędziłeś wiele moich wysiłków. – DearDhruv

+0

Cześć, podążam tą samą rzeczą co ty, ale dostaję dziwne wyniki. Właściwie moje dane wejściowe są wizytówką i za pomocą transformacji perspektywy chcę wyodrębnić tylko kartę z obrazu. Uzyskiwany obraz wyjściowy to po prostu pusty kolorowy obraz, który ma kolor z jednego z kolorów na karcie. – Manpreet

+0

@Aegonis działa to w jakiś sposób, ale czasami daje kopię lustrzaną ostatecznej bitmapy. ? jest to pożądane, przyjdź –

1

miałem pewne problemy z kodem, więc zrobiłem zmiany, dopóki nie dostanę działająca wersja, oto mój kod, jeśli ktoś miał problem z kodem pytającym:

Bitmap warp(Bitmap image, Point topLeft, Point topRight, Point bottomLeft, Point bottomRight) { 
    int resultWidth = (int)(topRight.x - topLeft.x); 
    int bottomWidth = (int)(bottomRight.x - bottomLeft.x); 
    if(bottomWidth > resultWidth) 
     resultWidth = bottomWidth; 

    int resultHeight = (int)(bottomLeft.y - topLeft.y); 
    int bottomHeight = (int)(bottomRight.y - topRight.y); 
    if(bottomHeight > resultHeight) 
     resultHeight = bottomHeight; 

    Mat inputMat = new Mat(image.getHeight(), image.getHeight(), CvType.CV_8UC1); 
    Utils.bitmapToMat(image, inputMat); 
    Mat outputMat = new Mat(resultWidth, resultHeight, CvType.CV_8UC1); 

    List<Point> source = new ArrayList<>(); 
    source.add(topLeft); 
    source.add(topRight); 
    source.add(bottomLeft); 
    source.add(bottomRight); 
    Mat startM = Converters.vector_Point2f_to_Mat(source); 

    Point ocvPOut1 = new Point(0, 0); 
    Point ocvPOut2 = new Point(resultWidth, 0); 
    Point ocvPOut3 = new Point(0, resultHeight); 
    Point ocvPOut4 = new Point(resultWidth, resultHeight); 
    List<Point> dest = new ArrayList<>(); 
    dest.add(ocvPOut1); 
    dest.add(ocvPOut2); 
    dest.add(ocvPOut3); 
    dest.add(ocvPOut4); 
    Mat endM = Converters.vector_Point2f_to_Mat(dest); 

    Mat perspectiveTransform = Imgproc.getPerspectiveTransform(startM, endM); 

    Imgproc.warpPerspective(inputMat, outputMat, perspectiveTransform, new Size(resultWidth, resultHeight)); 

    Bitmap output = Bitmap.createBitmap(resultWidth, resultHeight, Bitmap.Config.ARGB_8888); 
    Utils.matToBitmap(outputMat, output); 
    return output; 
} 
+0

Czy ten kod działa dobrze, to nie jest dla mnie trudne – Ata

+0

@Ata jaki był twój problem? – jonathanrz