web-dev-qa-db-ja.com

文字認識を行う前のOpenCVによる画像前処理(Tesseract)

ナンバープレート認識(Java + OpenCV + Tess4j)用のシンプルなPCアプリケーションを開発しようとしています。画像は本当に良くありません(さらに、それらは良いでしょう)。テッセラクトの画像を前処理したいのですが、ナンバープレートの検出(四角形の検出)に行き詰まっています。

私のステップ:

1)ソース画像

True Image

Mat img = new Mat();
img = Imgcodecs.imread("sample_photo.jpg"); 
Imgcodecs.imwrite("preprocess/True_Image.png", img);

2)グレースケール

Mat imgGray = new Mat();
Imgproc.cvtColor(img, imgGray, Imgproc.COLOR_BGR2GRAY);
Imgcodecs.imwrite("preprocess/Gray.png", imgGray);

3)ガウスぼかし

Mat imgGaussianBlur = new Mat(); 
Imgproc.GaussianBlur(imgGray,imgGaussianBlur,new Size(3, 3),0);
Imgcodecs.imwrite("preprocess/gaussian_blur.png", imgGaussianBlur);  

4)適応しきい値

Mat imgAdaptiveThreshold = new Mat();
Imgproc.adaptiveThreshold(imgGaussianBlur, imgAdaptiveThreshold, 255, CV_ADAPTIVE_THRESH_MEAN_C ,CV_THRESH_BINARY, 99, 4);
Imgcodecs.imwrite("preprocess/adaptive_threshold.png", imgAdaptiveThreshold);

これは、プレート領域の検出である5番目のステップであるはずです(おそらく今のところ、デスキューなしでも)。

私はペイントで必要な領域を(4番目のステップの後の)画像から切り取り、得ました:

plate region

次に、(tesseract、tess4jを介して)OCRを実行しました。

File imageFile = new File("preprocess/adaptive_threshold_AFTER_Paint.png");
ITesseract instance = new Tesseract();
instance.setLanguage("eng");
instance.setTessVariable("tessedit_char_whitelist", "acekopxyABCEHKMOPTXY0123456789");
String result = instance.doOCR(imageFile); 
System.out.println(result);

と(十分に良い?)結果を得た-"Y841ox EH"(ほぼ正しい)

4番目のステップの後にプレート領域を検出してトリミングするにはどうすればよいですか? 1〜4ステップでいくつかの変更(改善)を行う必要がありますか? Java + OpenCV(JavaCVではない))を介して実装されたいくつかの例を見たいと思います。
前もって感謝します。

[〜#〜] edit [〜#〜](@Abdul Fatirの回答に感謝)まあ、私は(少なくとも私にとって)機能するコードサンプル( Netbeans + Java + OpenCV + Tess4j)この質問に興味がある人のために。コードは最高ではありませんが、勉強のためだけに作りました。
http://Pastebin.com/H46wuXWntessdataフォルダーをプロジェクトフォルダーに入れることを忘れないでください)

14
DocC

これが私があなたがこの仕事をするべきだと提案する方法です。

  1. グレースケールに変換します。
  2. 3x3または5x5フィルターを使用したガウスぼかし。
  3. ソーベルフィルターを適用して垂直エッジを見つけます。

    Sobel(gray, dst, -1, 1, 0)

  4. 結果の画像にしきい値を設定して、バイナリ画像を取得します。
  5. 適切な構造化要素を使用して、モルフォロジークローズ操作を適用します。
  6. 結果の画像の輪郭を見つけます。
  7. 各輪郭のminAreaRectを見つけます。アスペクト比と最小および最大領域に基づいて長方形を選択します。
  8. 選択した各コンターについて、エッジ密度を見つけます。エッジ密度のしきい値を設定し、そのしきい値に違反する長方形を可能なプレート領域として選択します。
  9. この後、長方形はほとんど残りません。向きや、適切と思われる基準に基づいてフィルターをかけることができます。
  10. 検出されたこれらの長方形部分をadaptiveThresholdの後の画像から切り取り、OCRを適用します。

a)ステップ5の後の結果

Result after Step 5

b)ステップ7の後の結果。緑色のものはすべてminAreaRectsで、赤色のものは次の基準を満たすものです。アスペクト比の範囲(2,12)と面積の範囲(300) 、10000)

c)ステップ9の後の結果。選択された長方形。基準:エッジ密度> 0.5

enter image description here

[〜#〜]編集[〜#〜]

エッジ密度の場合、上記の例で私がしたことは次のとおりです。

  1. Canny Edge検出器を入力画像に直接適用します。 cannyED画像をIcとします。
  2. Sobelフィルターの結果とIcを乗算します。基本的に、SobelとCannyの画像のANDを取ります。
  3. ガウシアン大きなフィルターで結果の画像をぼかします。 21x21を使用しました。
  4. OTSUの方法を使用して、結果の画像にしきい値を設定します。バイナリイメージを取得します
  5. 赤い四角形ごとに、この四角形の内部(バイナリイメージ内)を回転させて、直立させます。長方形のピクセルをループして、白いピクセルを数えます。 ( 回転方法は?

エッジ密度=四角形の白ピクセル数/合計数長方形のピクセル数

  1. エッジ密度のしきい値を選択します。

[〜#〜]注[〜#〜]:手順1〜3を実行する代わりに、手順5のバイナリイメージを使用して、エッジ密度の計算。

12
Abdul Fatir

実際、OpenCVはロシアのナンバープレート用に事前にトレーニングされたモデルを持っています: haarcascade_russian_plate_number

また、ロシアのナンバープレート用のオープンソースANPRプロジェクトもあります: plate_recognition 。これはテッセラクトを使用していませんが、事前にトレーニングされたニューラルネットワークは非常に優れています。

2
sibnick
  • すべての接続されたコンポーネント(白い領域)を見つけ、それらの輪郭を決定します。
  • サイズ(画像の一部として)、比率(幅-高さ)、白と黒の比率に基づいてフィルターをかけ、候補プレートを取得します。
  • 長方形の変形を元に戻す
  • ボルトを外す
  • 画像をOCRエンジンに渡します。
1
RobAu