2013-08-02 45 views
2

我試圖自動化的過程,其中有人代碼手動轉換爲數字一體。的Java的OpenCV +正方體OCR「代碼」 regocnition

Analog code

然後,我開始閱讀關於OCR。所以我安裝了tesseract OCR並在一些圖像上試用了它。它甚至沒有檢測到與代碼接近的東西。

我讀計算器上的一些問題後算了一下,這些圖像需要一些預處理,如圖像歪斜的水平之一,它可以通過OpenCV進行例如已經完成。

現在我的問題是:

  • 應該像上面的圖像時,可以使用什麼樣的預處理或其他方法嗎?
  • 其次,我可以依靠輸出嗎?它會在像上面的圖像一樣的情況下工作嗎?

我希望有人能幫幫我!

回答

6

我已決定捕捉到整卡而不是僅僅的代碼。通過捕獲整個卡片,可以將其轉換爲簡單的視角,然後我可以輕鬆獲得「代碼」區域。

另外我學到了很多東西。特別是關於速度。此功能在高分辨率圖像上很慢。它可能需要長達10秒的大小爲3264 X 1836

我做了什麼,以加快速度,重新調整大小由1/4因子輸入矩陣。這使得它快了很多,並且給了我極小的精度損失。下一步是將我們找到的四邊形縮放到正常尺寸。因此,我們可以使用原始來源將四邊形轉換爲簡單的視角。

我檢測的最大區域創建的代碼是大量基於代碼,我計算器上找到。不幸的是,他們沒有像我預期的那樣工作,所以我組合了更多的代碼片段並進行了很多修改。 這是我的了:

private static double angle(Point p1, Point p2, Point p0) { 
     double dx1 = p1.x - p0.x; 
     double dy1 = p1.y - p0.y; 
     double dx2 = p2.x - p0.x; 
     double dy2 = p2.y - p0.y; 
     return (dx1 * dx2 + dy1 * dy2)/Math.sqrt((dx1 * dx1 + dy1 * dy1) * (dx2 * dx2 + dy2 * dy2) + 1e-10); 
    } 



    private static MatOfPoint find(Mat src) throws Exception { 
     Mat blurred = src.clone(); 
     Imgproc.medianBlur(src, blurred, 9); 

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

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

     List<Mat> blurredChannel = new ArrayList<>(); 
     blurredChannel.add(blurred); 
     List<Mat> gray0Channel = new ArrayList<>(); 
     gray0Channel.add(gray0); 

     MatOfPoint2f approxCurve; 

     double maxArea = 0; 
     int maxId = -1; 

     for (int c = 0; c < 3; c++) { 
      int ch[] = {c, 0}; 
      Core.mixChannels(blurredChannel, gray0Channel, new MatOfInt(ch)); 

      int thresholdLevel = 1; 
      for (int t = 0; t < thresholdLevel; t++) { 
       if (t == 0) { 
        Imgproc.Canny(gray0, gray, 10, 20, 3, true); // true ? 
        Imgproc.dilate(gray, gray, new Mat(), new Point(-1, -1), 1); // 1 ? 
       } else { 
        Imgproc.adaptiveThreshold(gray0, gray, thresholdLevel, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, (src.width() + src.height())/200, t); 
       } 

       Imgproc.findContours(gray, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); 

       for (MatOfPoint contour : contours) { 
        MatOfPoint2f temp = new MatOfPoint2f(contour.toArray()); 

        double area = Imgproc.contourArea(contour); 
        approxCurve = new MatOfPoint2f(); 
        Imgproc.approxPolyDP(temp, approxCurve, Imgproc.arcLength(temp, true) * 0.02, true); 

        if (approxCurve.total() == 4 && area >= maxArea) { 
         double maxCosine = 0; 

         List<Point> curves = approxCurve.toList(); 
         for (int j = 2; j < 5; j++) 
         { 

          double cosine = Math.abs(angle(curves.get(j % 4), curves.get(j - 2), curves.get(j - 1))); 
          maxCosine = Math.max(maxCosine, cosine); 
         } 

         if (maxCosine < 0.3) { 
          maxArea = area; 
          maxId = contours.indexOf(contour); 
          //contours.set(maxId, getHull(contour)); 
         } 
        } 
       } 
      } 
     } 

     if (maxId >= 0) { 
      return contours.get(maxId); 
      //Imgproc.drawContours(src, contours, maxId, new Scalar(255, 0, 0, .8), 8); 
     } 
     return null; 
    } 

你可以把它像這樣:

MathOfPoint contour = find(src); 

看到這個答案的四邊形檢測從輪廓和其轉化爲一個普通的觀點: Java OpenCV deskewing a contour

+0

我張貼的答案相關的問題,你貼在[OpenCV的論壇](http://answers.opencv.org/question/18101/java-opencv-tesseract-ocr-code-regocnition/) – tleyden

+0

感謝@Tim驗證碼對我非常有幫助但是我不得不對你的代碼做一些修改,因爲我無法得到如何用'MatOfPoint'在圖像周圍畫一個矩形。現在它爲我工作,但我仍然面臨一個問題。有時候這會在圖像上獲得一個只有一半的矩形,或者有時它會繪製多個矩形。你能告訴我一些如何解決這個問題。 – UltimateDevil