/ / Android:tesseract ocrによって取得された画像内の数字を改善するには? - java、アンドロイド、ocr、tesseract

Android:tesseract ocrで取得した画像内の数字を改善するには? - java、android、ocr、tesseract

画像を読む簡単なアプリを作りました。アンドロイドでテキストとして番号の画像を取得します。しかし問題は、精度が約60%しかなく、不要なノイズもあることです。私は正確さが100%と同じくらい良いことはありえないと思います、しかし、私はそれを改善する方法がなければならないと信じます。しかし、私はアマチュアなので難しいと思います。Googleで検索しましたが、確かな情報を得ることができませんでした。

下の画像のような東洋のラッキーチケットから596、00、および012345の番号を読みたいです。

ここに画像の説明を入力

回答:

回答№1は1

Tesseract-ocrは、次の基準を満たす文字の画像に最も適しています。

  • 入力画像は少なくとも300 dpi

  • 入力画像は白黒でなければなりません

  • 入力画像には最小限のノイズがあるはずです(つまり、テキストは背景と明確に区​​別できるはずです)。

  • テキスト行は直線でなければなりません

  • 画像は検出するテキストの中央に配置する必要があります

(詳しくはtesseract-ocr wikiを見てください)

与えられた入力画像に対して、tesseractはこれらの基準を満たすために画像を前処理してきれいにしようとしますが、あなたの検出精度を最大にするために、あなたはあなた自身で前処理をすることが最善です。

あなたが提供した入力画像に基づいて、メイン問題は、バックグラウンドノイズが多すぎることです。画像内のテキストから背景ノイズを除去するために、しきい値を使用してストローク幅変換(SWT)アルゴリズムを適用してノイズを除去すると、有望な結果が得られることがわかりました。多数の設定可​​能なパラメータを持つSWTの高速実装は、次のURLで提供されています。 libCCVライブラリ それがどのくらいよくそれをイメージをきれいにするかはイメージサイズ、ストローク幅の均一性とアルゴリズムへの他の入力パラメータを含む多くの要因に依存します。 設定可能なパラメータのリストはここにあります。

次に、SWTの出力をtesseractに渡して、画像内の文字のテキスト値を取得します。

tesseractに渡された画像にまだ含まれている場合多少のノイズ、句読文字などの誤った検出が返されることがあります。あなたが処理している画像が文字と数字a-z A-Z 0-9だけを含んでいる可能性が高いとすれば、あなたは単に最終的な誤検出を取り除くために出力に正規表現を適用することができます。


回答№2の場合は0
you can use Vision for text detection.

アプリgradleに依存関係を追加する

compile "com.google.android.gms:play-services-vision:10.0.0"

Manifest.xmlに追加する

<meta-data
android:name="com.google.android.gms.vision.DEPENDENCIES"
android:value="ocr" />

MainActivity.java

import android.app.AlertDialog;
import android.content.ContentValues;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.widget.TextView;

import com.google.android.gms.vision.Frame;
import com.google.android.gms.vision.text.TextBlock;
import com.google.android.gms.vision.text.TextRecognizer;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class MainActivity extends AppCompatActivity {
private static final int REQUEST_GALLERY = 0;
private static final int REQUEST_CAMERA = 1;

private static final String TAG = MainActivity.class.getSimpleName();

private Uri imageUri;
private TextView detectedTextView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

findViewById(R.id.choose_from_gallery).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, REQUEST_GALLERY);
}
});

findViewById(R.id.take_a_photo).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String filename = System.currentTimeMillis() + ".jpg";

ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, filename);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, REQUEST_CAMERA);
}
});

detectedTextView = (TextView) findViewById(R.id.detected_text);
detectedTextView.setMovementMethod(new ScrollingMovementMethod());
}

private void inspectFromBitmap(Bitmap bitmap) {
TextRecognizer textRecognizer = new TextRecognizer.Builder(this).build();
try {
if (!textRecognizer.isOperational()) {
new AlertDialog.
Builder(this).
setMessage("Text recognizer could not be set up on your device").show();
return;
}

Frame frame = new Frame.Builder().setBitmap(bitmap).build();
SparseArray<TextBlock> origTextBlocks = textRecognizer.detect(frame);
List<TextBlock> textBlocks = new ArrayList<>();
for (int i = 0; i < origTextBlocks.size(); i++) {
TextBlock textBlock = origTextBlocks.valueAt(i);
textBlocks.add(textBlock);
}
Collections.sort(textBlocks, new Comparator<TextBlock>() {
@Override
public int compare(TextBlock o1, TextBlock o2) {
int diffOfTops = o1.getBoundingBox().top - o2.getBoundingBox().top;
int diffOfLefts = o1.getBoundingBox().left - o2.getBoundingBox().left;
if (diffOfTops != 0) {
return diffOfTops;
}
return diffOfLefts;
}
});

StringBuilder detectedText = new StringBuilder();
for (TextBlock textBlock : textBlocks) {
if (textBlock != null && textBlock.getValue() != null) {
detectedText.append(textBlock.getValue());
detectedText.append("n");
}
}

detectedTextView.setText(detectedText);
}
finally {
textRecognizer.release();
}
}

private void inspect(Uri uri) {
InputStream is = null;
Bitmap bitmap = null;
try {
is = getContentResolver().openInputStream(uri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inSampleSize = 2;
options.inScreenDensity = DisplayMetrics.DENSITY_LOW;
bitmap = BitmapFactory.decodeStream(is, null, options);
inspectFromBitmap(bitmap);
} catch (FileNotFoundException e) {
Log.w(TAG, "Failed to find the file: " + uri, e);
} finally {
if (bitmap != null) {
bitmap.recycle();
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
Log.w(TAG, "Failed to close InputStream", e);
}
}
}
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_GALLERY:
if (resultCode == RESULT_OK) {
inspect(data.getData());
}
break;
case REQUEST_CAMERA:
if (resultCode == RESULT_OK) {
if (imageUri != null) {
inspect(imageUri);
}
}
break;
default:
super.onActivityResult(requestCode, resultCode, data);
break;
}
}
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="org.komamitsu.android_ocrsample.MainActivity">


<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/choose_from_gallery"
android:id="@+id/choose_from_gallery"
tools:context=".MainActivity"
android:layout_marginTop="23dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/take_a_photo"
android:id="@+id/take_a_photo"
tools:context=".MainActivity"
android:layout_marginTop="11dp"
android:layout_below="@+id/choose_from_gallery"
android:layout_centerHorizontal="true" />


<TextView
android:text=""
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/detected_text"
android:layout_alignParentBottom="true"
android:layout_below="@+id/take_a_photo"
android:layout_margin="25dp"
android:layout_centerHorizontal="true"
android:background="#EEEEEE"
android:scrollbars="vertical" />

</RelativeLayout>