2013-10-30 8 views
18

Ich möchte eine Anwendung wie ein Cam-Scanner zum Zuschneiden eines Dokuments machen.So führen Sie die automatische Zuschneidung für das Dokument durch Erkennen des Bildes mit der Kamera?

Aber ich brauche gleiche Funktionalität wie meine beiden Bilder ..

Erste Bilder Bild von der Kamera ..

enter image description here

Zweites Bild erkennen, wie diese erfasst gezeigt ein aufgenommenes Bild Teil ..

enter image description here

Ich recherchiere mehr und mehr, aber bekomme keinen out so, Ich bitte hier, wenn irgendeine dieser mir getan sagen ..

Dank

+0

Check it out [diese ein ] (http://answers.opencv.org/question/17607/searching-for-a-good-object-detection-tutorial-on/) hoffe, es hilft. –

Antwort

11

Ich gehe davon aus, Ihr Problem ist, das Objekt zu erkennen, zu scannen.

Objekterkennungsmechanismen wie Mustererkennung oder Merkmalserkennung bringen Ihnen nicht die gewünschten Ergebnisse, da Sie nicht genau wissen, was genau das zu scannende Objekt ist.

Grundsätzlich suchen Sie nach einem rechteckigen Objekt im Bild.

Ein grundlegender Ansatz könnte wie folgt aussehen:

  • auf dem Bild canny edge detector starten. Es könnte helfen, das Bild ein wenig zu verwischen, bevor Sie dies tun. Die Kanten des Objekts sollten deutlich sichtbar sein.

  • Jetzt möchten Sie eine Hough transform tun, um Linien im Bild zu finden.

  • Suchen Sie nach Linien mit einem Winkel von 90 Grad zueinander. Das Problem wäre, die richtigen zu finden. Vielleicht ist es genug, die Linien zu verwenden, die dem Bildrahmen am nächsten sind, die ziemlich parallel zu ihnen sind.

  • Suchen Sie die Schnittpunkte, um die Kanten Ihres Objekts zu definieren.

Zumindest sollte Ihnen das einen Hinweis geben, wo Sie weiter forschen können.

Als weitere Schritte in einer solchen App müssen Sie die Projektion der Punkte berechnen und eine affine Transformation des Objekts durchführen.

Ich hoffe, das hilft.

Nachdem ich all das geschrieben habe, fand ich this post. Es sollte Ihnen helfen, viel.

Als meine Antwort Ziele OpenCV müssen Sie die OpenCV-Bibliothek verwenden. Um dies zu tun, müssen Sie die installieren. Es gibt einige gute Tutorials zur Verwendung von OpenCV unter Android auf der OpenCV for Android Seite.

Eine Sache zu beachten ist, dass fast jede Funktion des Java-Wrappers eine native Methode aufruft. Das kostet viel Zeit.Daher möchten Sie so viel wie möglich in Ihrem systemeigenen Code ausführen, bevor Sie Ihre Ergebnisse an den Java-Teil zurücksenden.

+0

wie in android nativen diese code zu implementieren .. – Roadies

+0

Ich sah, dass dies mit OpenCV hinterher markiert wurde, so fügte ich einen Teil über OpenCV und die nativen Tools. Es gibt einige gute Tutorials dazu. – Grey

+0

Irgendeine Idee, wie man dieses Verfahren ändert, ich meine, es mit fast demselben Hintergrund wie vom Dokument arbeiten zu lassen? –

5

Ich weiß, ich bin zu spät zu beantworten, aber es könnte für jemanden hilfreich sein.

Versuchen Sie den folgenden Code.

@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

ich mit Code ein Git-Repo erstellt haben für native Unterstützung, das Bild auf die richtige Weise zu beschneiden, finden Sie es auf: link.

Fühlen Sie sich frei, Code zu bearbeiten, wenn Sie mit einer besseren Lösung kommen.

0

Fahren Sie mit Bild Matte in dieser Methode:

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

        } 
       } 
      } 
     } 
    } 
} 

Bei dieser Methode Sie vier Punkt des Dokuments erhalten, dann können Sie das Bild mit folgenden Verfahren geschnitten:

 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; 
} 
Verwandte Themen