2017-05-14 3 views
0

バウンディングボックスが正常に検出されました。イメージの他の部分をすべて削除し、境界ボックスの内容を残してテセラクト精度を向上させたいと考えています。行われ、必要にしている(私はバイナリイメージは文字だけを含むようにしたい、他のすべてのオブジェクトが削除される):OpenCV Javaシーンからオブジェクトを削除する

I want the binary images to only contain the letters, all the other objects to be removed

と私のコードを:

public static ProcessedFrame preProcessImage(Mat image){ 
    originalFrame = image.clone(); 
    roiColor = image.clone(); 
    Imgproc.cvtColor(image, image, Imgproc.COLOR_BGR2GRAY, 0); 
    originalFrameGrayScale = image.clone(); 
    Mat morph = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(9, 9)); 
    Imgproc.morphologyEx(image, image, Imgproc.MORPH_TOPHAT, morph); 
    Imgproc.Sobel(image, image, -1, 2, 0); 
    Imgproc.GaussianBlur(image, image, new Size(5,5), 3,3); 
    Imgproc.morphologyEx(image, image, Imgproc.MORPH_CLOSE, morph); 
    Imgproc.threshold(image, image, 200, 255, Imgproc.THRESH_OTSU); 
    Vector<Rect> rectangles = detectionContour(image); 
    Mat roi = originalFrameGrayScale.clone(); 
    if(!rectangles.isEmpty()){ 
    roi = originalFrameGrayScale.submat(rectangles.get(0)); 
    roiBlack = roi.clone(); 
    roiColor = roiColor.submat(rectangles.get(0)); 
     Imgproc.rectangle(originalFrame, rectangles.get(0).br(), rectangles.get(0).tl(), new Scalar(0,0,255), 2); 
    } 
    Imgproc.medianBlur(roi, roi, 3); 
    Imgproc.adaptiveThreshold(roi, roi, 225, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 15, 3); 
    Imgproc.medianBlur(roi, roi, 3); 
    Imgproc.medianBlur(roi, roi, 3); 
    Imgproc.adaptiveThreshold(roi, roi, 225, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 15, 3); 
    Imgproc.medianBlur(roi, roi, 3); 
    roiBinarize = roi.clone(); 
    Mat erode = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3)); 
    Mat dilate = Imgproc.getStructuringElement(Imgproc.MORPH_RECT,new Size(3, 3)); 
    Imgproc.morphologyEx(roi, roi, Imgproc.MORPH_CLOSE, dilate); 
    Imgproc.morphologyEx(roi, roi, Imgproc.MORPH_CLOSE, erode); 
    Vector<Rect> letters = detectionPlateCharacterContour(roi); 
    doTesseractOCR(letters, roiBinarize); 
    return new ProcessedFrame(originalFrame, roiColor, roiBinarize, roi); 

} 






private static void doTesseractOCR(Vector<Rect> letters, Mat plate){ 
    Tesseract instance = new Tesseract(); // 
    instance.setLanguage(LANGUAGE); 
    String resultPlate = "AAA0000"; 
    for(int i= 0; i < letters.size(); i++){ 

    BufferedImage letter = OpenCvUtils.Mat2bufferedImage(plate.submat(letters.get(i))); 
     try { 
     String result = instance.doOCR(letter); 
     String character = result.replace("\n", ""); 
     resultPlate = new StringBuilder(resultPlate).replace(i ,i+1, character).toString(); 
     } catch (TesseractException e) { 
     System.err.println(e.getMessage()); 
     } 

     System.out.println("Tesseract output: "+resultPlate); 
    } 

    try { 
     String result = instance.doOCR(OpenCvUtils.Mat2bufferedImage(roiBinarize)); 
     System.out.println("Tesseract output2: "+result.replace("\n", "")); 
     } catch (TesseractException e) { 
     System.err.println(e.getMessage()); 
     } 
} 





private static Vector<Rect> detectionPlateCharacterContour(Mat roi) { 
    Mat contHierarchy = new Mat(); 
    Mat imageMat = roi.clone(); 
    Rect rect = null; 
    List<MatOfPoint> contours = new ArrayList<>(); 
    Imgproc.findContours(imageMat, contours, contHierarchy, Imgproc.RETR_CCOMP, Imgproc.CHAIN_APPROX_SIMPLE); 
    Vector<Rect> rect_array = new Vector<>(); 

    for (int i = 0; i < contours.size(); i++) { 
     rect = Imgproc.boundingRect(contours.get(i)); 
     double ratio = 0; 

       if(rect.height > rect.width){ 
      ratio = rect.height/rect.width; 

      }else{ 
       ratio = rect.width/rect.height; 

      } 
     Logger.printMessage("Ratio of letter: "+ratio); 
     double contourarea = Imgproc.contourArea(contours.get(i)); 
     if (contourarea >= 160 && contourarea <= 1000 && (ratio >= 1 && ratio <= 2)) { 
     Imgproc.rectangle(roiColor, rect.br(), rect.tl(), new Scalar(10,50,255)); 
      rect_array.add(rect); 
     } 
    } 


    contHierarchy.release(); 
    return rect_array; 
} 




private static Vector<Rect> detectionContour(Mat outmat) { 
    Mat contHierarchy = new Mat(); 
    Mat imageMat = outmat.clone(); 

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

    Imgproc.findContours(imageMat, contours, contHierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_NONE); 

    Vector<Rect> rect_array = new Vector<>(); 
    for (int i = 0; i < contours.size(); i++) { 
     Rect rect = Imgproc.boundingRect(contours.get(i)); 

     Mat contour = contours.get(i); 
     double contourarea = Imgproc.contourArea(contour); 

      double ratio = 0; 
      int radius = 0; 
      if(rect.height > rect.width){ 
      ratio = rect.height/rect.width; 
      radius = rect.height/2; 
      }else{ 
       ratio = rect.width/rect.height; 
       radius = rect.width/2; 
      } 
     if (contourarea >= 2000 && contourarea <= 10000 && (ratio == 1 || ratio == 2)) { 
      Logger.printMessage("Rectangle ratio: "+ratio); 
      MatOfPoint2f mat2f = new MatOfPoint2f(); 
      contours.get(i).convertTo(mat2f, CvType.CV_32FC2); 
      RotatedRect rotatedRect = Imgproc.minAreaRect(mat2f); 
      double rotationAngle = rotatedRect.angle; 
      if(rotatedRect.angle > 0) 
       rotationAngle = 90 - rotatedRect.angle; 
      else 
       rotationAngle = rotatedRect.angle; 
      Logger.printMessage("Rotation is: "+(rotationAngle)); 
      rect = enlargeROI(originalFrame, rect, 10); 
      rect_array.add(rect); 
     } 
    } 


    contHierarchy.release(); 
    return rect_array; 
} 





private Vector<Rect> detectionContours(Mat outmat) { 
    Mat contHierarchy = new Mat(); 
    Mat imageMat = outmat.clone(); 
    Rect contourRect = null; 
    List<MatOfPoint> contours = new ArrayList<>(); 
    Imgproc.findContours(imageMat, contours, contHierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); 
    Vector<Rect> rect_array = new Vector<>(); 
    for (int i = 0; i < contours.size(); i++) { 
     Mat contour = contours.get(i); 
     double contourarea = Imgproc.contourArea(contour); 
     if (contourarea > minBlob && contourarea < maxBlob) { 
      contourRect = Imgproc.boundingRect(contours.get(i)); 
      rect_array.add(contourRect); 
     } 
    } 


    contHierarchy.release(); 
    return rect_array; 
} 

私はこのコードを実行しますその18.0 Y:111.0 2×:42.0 Y:109.0 7×:65.0 Y:108.0 0X:89.0 Y:108.0 X:29.0 Y:61.0 CのX: 2×iが見つける各矩形の重心52.0 Y:58.0 PのX:77.0 Y:58.0

+0

可能な複製を取得したいhttp://stackoverflow.com/questions/43958962/opencv-enhancing-image-for-ocr) - 明らかに同じ問題が何であるか別の質問を投稿するのではなく、元の質問を適切に改善してください。 –

+0

投稿を削除しました。間違って質問されました。 –

+0

OK:|あなたが「取り除く」イメージの部分を置き換えたいものは何ですか? (添付された画像の右下隅にある画像を使って、それを行うためのいくつかのさらなるステップについて話していると仮定します)。tesseractに、検出された個々の文字を指定する境界ボックスのベクトルを供給するので、表示のために? –

答えて

0

あなたがちょうど境界ボックスあなたの手紙に、いくつかの前処理を行う必要があるようで、それは厳密ではないのですが、それはおそらく、たTesseractにそれらを供給する前にそれを行うには理にかなって必要。私たちのサンプル画像に輪郭インデックスを付け、その属性を集計することから始めましょう。

Annotated LP

contour | bbox centroid | recognised 
index | x | y | symbol 
--------+-------+-------+----------- 
0  | 18.0 | 111.0 | 2 
1  | 42.0 | 109.0 | 2 
2  | 65.0 | 108.0 | 7 
3  | 89.0 | 108.0 | 0 
4  | 29.0 | 61.0 | A 
5  | 52.0 | 58.0 | C 
6  | 77.0 | 58.0 | P 

人が、このナンバープレートを読み取ると、彼らはシンボルの一番上の行で始まり、左から右にシンボルを読み込みます。右端のシンボルに達すると、次の下の行に移動し、再び左から右に移動します。したがって、私たちはこれを簡単に行えるような構造でシンボル(またはシンボルを表すバウンディングボックス)を整理する必要があります。

Vector<Rect>を使用して、シンボルの各行を表すことができます。常に2行のシンボルがあるので、このベクトルの2つのインスタンスが必要です。ロー0ロー1と呼ぶことにします。


最初のタスクはシンボルの境界ボックスを2つのグループに分類し、これに基づいて適切な行ベクトルに追加します。これに対する簡単なアプローチは、次のようなものです。

  • シンボル重心の座標の平均値を計算します。この例では、約mean_y=87.5です。各検出されたシンボルについて
    • シンボル重心の座標y場合がmean_y未満である、そうでなければROW1
に記号を追加 ROW0
  • に記号を追加します

    サンプルのシンボルセットでこのアルゴリズムを実行すると、

     | contained 
    row | symbol ids 
    -----+-------------- 
    row0 | 4, 5, 6 
    row1 | 0, 1, 2, 3 
    

    この単純なアプローチが不十分であると判明した場合は、さらに進んだmeans of clusteringを試すことができます。

    • 各行について:


      第2のタスクは、シンボルが左から右へ行くように各列をソートすることであるxで昇順に

      • 並べ替え行要素の座標、その重心

    私のJavaはかなり錆びていますが、おそらくcomparatorを使ってこれを行うことができます。 Javaでコレクションをソートする方法の詳細については、this SO answerを参照してください。 :私たちのサンプルで

    、今

     | contained 
    row | symbol ids 
    -----+-------------- 
    row0 | 4, 5, 6 
    row1 | 0, 1, 2, 3 
    

    私たちすることができます行ごとに

    • ...各行内の要素を順番に既にある、そうするものは何もありません
      • 行内の各シンボルについて
        • テセラクト処理
        • 必要に応じて結果を処理します。プリント)私たちのサンプルで

    、我々は([OCRのためのOpenCVの画像強調]の

    ACP 
    2270 
    
  • 関連する問題