2013-10-30 10 views
18

Chcę utworzyć aplikację podobną do skanera z kamerą do przycinania dokumentu.Jak wykonać Automatyczne przycinanie dla dokumentu Rozpoznawanie obrazu za pomocą kamery?

Ale muszę taką samą funkcjonalność jak moich dwóch obrazów ..

Pierwsze obrazy pokazywane obraz zarejestrowany przez kamery ..

enter image description here

Drugi obraz rozpoznają przechwycony część obrazu tak ..

enter image description here

Badam coraz więcej, ale nie mogę się z tym pogodzić, Pytam tutaj, jeśli nikomu zrobić to powiedzieć ..

Thanks

+0

Sprawdź to [ten jeden ] (http://answers.opencv.org/question/17607/searching-for-a-good-object-detection-tutorial-on/) nadzieję, że to pomaga. –

Odpowiedz

11

I zakładamy, że problemem jest to, aby wykryć obiekt do skanowania.

Mechanizmy wykrywania obiektów, takie jak dopasowywanie wzorców lub wykrywanie cech, nie przyniosą pożądanych wyników, ponieważ nie wiesz, jaki dokładnie obiekt skanujesz.

Zasadniczo szukasz obiektu prostokątnego na zdjęciu.

Podstawowym podejściem do tego może być następujący:

  • Uruchom canny edge detector na obrazie. Pomoże to nieco zamazać obraz. Krawędzie obiektu powinny być wyraźnie widoczne.

  • Teraz chcesz zrobić Hough transform, aby znaleźć linie na rysunku.

  • Wyszukaj linie pod kątem 90 stopni względem siebie. Problem polega na znalezieniu właściwych. Być może wystarczy użyć linii najbliżej ramy obrazu, które są do siebie racjonalnie równoległe.

  • Znajdź przecinające się punkty, aby zdefiniować krawędzie swojego obiektu.

Przynajmniej to powinno dać wskazówkę, gdzie dalej szukać.

Jako kolejne kroki w takiej aplikacji będziesz musiał obliczyć rzut punktów i wykonać transformację afiniczną obiektu.

Mam nadzieję, że to pomoże.

Po napisaniu tego wszystkiego znalazłem this post. To powinno ci pomóc.

Jako że moja odpowiedź jest skierowana do OpenCV, należy użyć biblioteki OpenCV. Aby to zrobić, musisz zainstalować Android Native Development Kit (NDK). Istnieje kilka dobrych samouczków dotyczących korzystania z OpenCV na Androida na stronie OpenCV for Android.

Należy pamiętać, że prawie każda funkcja opakowania Java nazywa metodę natywną. To kosztuje dużo czasu.Więc chcesz zrobić jak najwięcej w swoim natywnym kodzie przed zwróceniem twoich wyników do części Javy.

+0

jak zaimplementować w systemie Android ten kod. – Roadies

+0

Widziałem, że został oznaczony OpenCV później, więc dodałem część dotyczącą OpenCV i rodzimych narzędzi. Jest kilka dobrych tutoriali na ten temat. – Grey

+0

Jakikolwiek pomysł na modyfikację tej procedury, mam na myśli, aby działał na tym samym tle co dokument? –

5

Wiem, że jestem już za późno, aby odpowiedzieć, ale może to być pomocne dla kogoś.

Spróbuj następującego kodu.

@Override 
protected void onDraw(Canvas canvas) { 

    super.onDraw(canvas); 
    path = new Path(); 

    path.moveTo(x1, y1);  // this should set the start point right 

    //path.lineTo(x1, y1); <-- this line should be drawn at the end of  course,sorry 
    path.lineTo(x2, y2); 
    path.lineTo(x3, y3); 
    path.lineTo(x4, y4); 
    path.lineTo(x1, y1); 
    canvas.drawPath(path, currentPaint); 

} 
0

Utworzono repo git z kodem na rodzimy wsparcie, czyli przycinanie obrazu we właściwy sposób, znajdziesz na: link.

Jeśli masz lepsze rozwiązanie, możesz edytować kod.

0

Przełóż matę obrazu w tej metody:

 void findSquares(Mat image, List<MatOfPoint> squares) { 
    int N = 10; 

    squares.clear(); 

    Mat smallerImg = new Mat(new Size(image.width()/2, image.height()/2), image.type()); 

    Mat gray = new Mat(image.size(), image.type()); 

    Mat gray0 = new Mat(image.size(), CvType.CV_8U); 

    // down-scale and upscale the image to filter out the noise 
    Imgproc.pyrDown(image, smallerImg, smallerImg.size()); 
    Imgproc.pyrUp(smallerImg, image, image.size()); 
    // find squares in every color plane of the image 
    Outer: 
    for (int c = 0; c < 3; c++) { 

     extractChannel(image, gray, c); 

     // try several threshold levels 
     Inner: 
     for (int l = 1; l < N; l++) { 

      Imgproc.threshold(gray, gray0, (l + 1) * 255/N, 255, Imgproc.THRESH_BINARY); 


      List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); 

      // find contours and store them all as a list 
      Imgproc.findContours(gray0, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); 

      MatOfPoint approx = new MatOfPoint(); 

      // test each contour 
      for (int i = 0; i < contours.size(); i++) { 

       approx = approxPolyDP(contours.get(i), Imgproc.arcLength(new MatOfPoint2f(contours.get(i).toArray()), true) * 0.02, true); 

       // square contours should have 4 vertices after approximation 
       // relatively large area (to filter out noisy contours) 
       // and be convex. 
       // Note: absolute value of an area is used because 
       // area may be positive or negative - in accordance with the 
       // contour orientation 
       double area = Imgproc.contourArea(approx); 

       if (area > 5000) { 

        if (approx.toArray().length == 4 && 
          Math.abs(Imgproc.contourArea(approx)) > 1000 && 
          Imgproc.isContourConvex(approx)) { 

         double maxCosine = 0; 
         Rect bitmap_rect = null; 
         for (int j = 2; j < 5; j++) { 
          // find the maximum cosine of the angle between joint edges 
          double cosine = Math.abs(angle(approx.toArray()[j % 4], approx.toArray()[j - 2], approx.toArray()[j - 1])); 
          maxCosine = Math.max(maxCosine, cosine); 
          bitmap_rect = new Rect(approx.toArray()[j % 4], approx.toArray()[j - 2]); 

         } 

         // if cosines of all angles are small 
         // (all angles are ~90 degree) then write quandrange 
         // vertices to resultant sequence 
         if (maxCosine < 0.3) 
          squares.add(approx); 

        } 
       } 
      } 
     } 
    } 
} 

W tej metodzie można uzyskać cztery punkt dokumentu następnie można wyciąć ten obraz za pomocą poniższego sposobu:

 public Bitmap warpDisplayImage(Mat inputMat) { 
    List<Point> newClockVisePoints = new ArrayList<>(); 

    int resultWidth = inputMat.width(); 
    int resultHeight = inputMat.height(); 

    Mat startM = Converters.vector_Point2f_to_Mat(orderRectCorners(Previes method four poit list(like : List<Point> points))); 

    Point ocvPOut4 = new Point(0, 0); 
    Point ocvPOut1 = new Point(0, resultHeight); 
    Point ocvPOut2 = new Point(resultWidth, resultHeight); 
    Point ocvPOut3 = new Point(resultWidth, 0); 



     ocvPOut3 = new Point(0, 0); 
     ocvPOut4 = new Point(0, resultHeight); 
     ocvPOut1 = new Point(resultWidth, resultHeight); 
     ocvPOut2 = new Point(resultWidth, 0); 
    } 

    Mat outputMat = new Mat(resultWidth, resultHeight, CvType.CV_8UC4); 

    List<Point> dest = new ArrayList<Point>(); 
    dest.add(ocvPOut3); 
    dest.add(ocvPOut2); 
    dest.add(ocvPOut1); 
    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), Imgproc.INTER_CUBIC); 


    Bitmap descBitmap = Bitmap.createBitmap(outputMat.cols(), outputMat.rows(), Bitmap.Config.ARGB_8888); 
    Utils.matToBitmap(outputMat, descBitmap); 



    return descBitmap; 
} 
Powiązane problemy