Java Android:如何改善tesseract ocr检索到的图像中的数字?

Java Android:如何改善tesseract ocr检索到的图像中的数字?,java,android,ocr,tesseract,Java,Android,Ocr,Tesseract,我用android制作了一个简单的应用程序,可以读取图像并以文本形式检索数字图像。但问题是,准确率只有60%左右,一些不必要的噪声也会显示出来。我确实认为准确率不可能达到100%,但是,我相信一定有办法改进它。但是,因为我是个业余爱好者,我觉得很难。我在谷歌搜索过,但无法获得可靠的信息 我想读一张东方幸运票上的数字596、00和012345,如下图所示 Tesseract ocr最适用于符合以下标准的字符图像: 输入图像应至少具有300 dpi 输入图像应该是黑白的 输入图像中的噪声应最小(即

我用android制作了一个简单的应用程序,可以读取图像并以文本形式检索数字图像。但问题是,准确率只有60%左右,一些不必要的噪声也会显示出来。我确实认为准确率不可能达到100%,但是,我相信一定有办法改进它。但是,因为我是个业余爱好者,我觉得很难。我在谷歌搜索过,但无法获得可靠的信息

我想读一张东方幸运票上的数字596、00和012345,如下图所示


Tesseract ocr最适用于符合以下标准的字符图像:

  • 输入图像应至少具有300 dpi

  • 输入图像应该是黑白的

  • 输入图像中的噪声应最小(即文本应与背景清晰区分)

  • 文本行应该是直的

  • 图像应围绕要检测的文本居中

对于给定的输入图像,tesseract将尝试预处理和清理图像以满足这些标准,但为了最大限度地提高检测精度,最好自己进行预处理

根据您提供的输入图像,主要问题是背景噪声太大。为了去除图像中文本的背景噪声,我发现应用带有阈值的笔划宽度变换(SWT)算法来去除噪声会得到很好的结果。SWT的快速实现提供了许多可配置的参数,其清洁图像的程度取决于许多因素,包括图像大小、笔划宽度均匀性和算法的其他输入参数

然后将SWT的输出传递给tesseract,以获取图像中字符的文本值

如果传递给tesseract的图像仍然包含一些噪波,则可能返回一些错误检测,例如标点符号。考虑到您正在处理的图像可能只包含字母和数字a-z a-z 0-9,您可以简单地对输出应用正则表达式,以消除任何最终的错误检测

在app gradle中添加依赖项

外接程序Manifest.xml


MainActivity.java

导入android.app.AlertDialog;
导入android.content.ContentValues;
导入android.content.Intent;
导入android.graphics.Bitmap;
导入android.graphics.BitmapFactory;
导入android.net.Uri;
导入android.provider.MediaStore;
导入android.support.v7.app.AppActivity;
导入android.os.Bundle;
导入android.text.method.ScrollingMovementMethod;
导入android.util.DisplayMetrics;
导入android.util.Log;
导入android.util.SparseArray;
导入android.view.view;
导入android.widget.TextView;
导入com.google.android.gms.vision.Frame;
导入com.google.android.gms.vision.text.TextBlock;
导入com.google.android.gms.vision.text.TextRecognizer;
导入java.io.FileNotFoundException;
导入java.io.IOException;
导入java.io.InputStream;
导入java.util.ArrayList;
导入java.util.Collections;
导入java.util.Comparator;
导入java.util.List;
公共类MainActivity扩展了AppCompatActivity{
私有静态最终整数请求\u GALLERY=0;
专用静态最终int请求\u摄像机=1;
私有静态最终字符串标记=MainActivity.class.getSimpleName();
私有Uri-imageUri;
私有文本视图检测到文本视图;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.choose_from_gallery).setOnClickListener(new View.OnClickListener()){
@凌驾
公共void onClick(视图v){
意图=新意图();
intent.setType(“image/*”);
intent.setAction(intent.ACTION\u GET\u CONTENT);
startActivityForResult(意向、请求);
}
});
findviewbyd(R.id.take_a_photo).setOnClickListener(newview.OnClickListener()){
@凌驾
公共void onClick(视图v){
字符串文件名=System.currentTimeMillis()+“.jpg”;
ContentValues=新的ContentValues();
value.put(MediaStore.Images.Media.TITLE,文件名);
value.put(MediaStore.Images.Media.MIME_类型,“image/jpeg”);
imageUri=getContentResolver().insert(MediaStore.Images.Media.EXTERNAL\u CONTENT\u URI,值);
意图=新意图();
intent.setAction(MediaStore.ACTION\u IMAGE\u CAPTURE);
intent.putExtra(MediaStore.EXTRA_输出,imageUri);
startActivityForResult(意图、请求和摄像头);
}
});
detectedTextView=(TextView)findViewById(R.id.detected\u text);
detectedTextView.setMovementMethod(新的ScrollingMovementMethod());
}
私有void inspectFromBitmap(位图位图){
TextRecognizer TextRecognizer=新的TextRecognizer.Builder(this.build();
试一试{
如果(!textRecognitor.isOperational()){
新建警报对话框。
建筑商(这个)。
setMessage(“无法在设备上设置文本识别器”).show();
返回;
}
Frame Frame=new Frame.Builder().setbit映射(位图).build();
SparseArray origTextBlocks=文本识别器。检测(帧);
List textBlocks=new ArrayList();
对于(int i=0;iyou can use Vision for text detection.
compile 'com.google.android.gms:play-services-vision:10.0.0'
<meta-data
        android:name="com.google.android.gms.vision.DEPENDENCIES"
        android:value="ocr" />
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;
        }
    }
}
<?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>