2013-08-02 2 views
2

Я пытаюсь автоматизировать процесс, когда кто-то вручную преобразует код в цифровой.Java OpenCV + Tesseract OCR «код» regocnition

Analog code

Тогда я начал читать о OCR. Поэтому я установил Tesseract OCR и попробовал его на некоторых изображениях. Он даже не обнаруживает что-то близкое к коду.

Я понял, что, прочитав некоторые вопросы о stackoverflow, изображения нуждаются в некоторой предварительной обработке, например, перекручивании изображения на горизонтальное, что может быть сделано с помощью openCV, например.

Теперь мои вопросы:

  • Какие препроцессора или другие методы должны быть использованы в таком случае, как на картинке?
  • Во-вторых, могу ли я полагаться на выход? Будет ли он всегда работать в случаях, подобных приведенному выше изображению?

Я надеюсь, что кто-то может мне помочь!

ответ

6

Я решил захватить всю карту вместо кода. Захватив всю карту, можно преобразовать ее в простой вид, а затем я легко могу получить область «кода».

Также я многому научился. Особенно в отношении скорости. Эта функция работает медленно на изображениях с высоким разрешением. Это может занять до 10 секунд с размером 3264 x 1836.

Что я сделал, чтобы ускорить процесс, переформатирует входную матрицу в 1/4. Это делает его 4^2 раз быстрее и дал мне минимальную потерю точности. Следующим шагом будет масштабирование четырехугольника, который мы вернулись к нормальному размеру. Так что мы можем преобразовать четырехугольник в простой перспективе с использованием исходного источника.

Код, который я создал для обнаружения наибольшей площади, в значительной степени основан на коде, который я нашел в stackoverflow. К сожалению, они не работали так, как ожидалось для меня, поэтому я объединил больше фрагментов кода и многое изменил. Это то, что я получил:

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 forum] (http://answers.opencv.org/question/18101/java-opencv-tesseract-ocr-code-regocnition/) – tleyden

+0

Спасибо @Tim этот код настолько полезен для меня. Но я должен внести некоторые изменения в ваш код, потому что я не могу получить, как рисовать прямоугольник вокруг изображения с помощью «MatOfPoint». Теперь он работает для меня, но я все еще сталкиваюсь с проблемой. Иногда это получает только половину прямоугольника на изображении, или иногда он рисует несколько прямоугольников. Можете ли вы предложить мне что-то, как решить эту проблему. – UltimateDevil

Смежные вопросы