【问题标题】:Android: How to improve the numbers within the image retrieved by tesseract ocr?Android:如何改进tesseract ocr检索到的图像中的数字?
【发布时间】:2015-03-27 00:00:05
【问题描述】:

我制作了一个简单的应用程序,它可以读取图像并使用 android 将数字图像作为文本检索。但问题是准确度只有 60% 左右,而且还会出现一些不需要的噪音。我确实认为准确率不可能达到 100%,但是,我相信必须有办法改进它。但是,由于我是业余爱好者,我觉得很难。我搜索了谷歌,但无法获得可靠的信息。

我想从东方幸运票中读取数字 596 、 00 和 012345 ,如下图所示。

【问题讨论】:

  • 您使用的是最新的语言包(3.02)吗? code.google.com/p/tesseract-ocr/downloads/…。还要确保拍摄的相机图像是高质量的。尽量减少位图下采样。
  • 是的,当前使用的包是最新版本。
  • 我使用的设备是 Nexus 5,所以我相信相机的像素还不错..但可能没那么好。你的意思是我必须在拍摄照片后更改图像的位图大小(更改代码)吗?还有一件事让我担心,但是训练 tesseract 会影响输出吗?
  • 拍照后无需修改位图,使用原图即可。我不确定 tesseract 培训。

标签: java android ocr tesseract


【解决方案1】:

Tesseract-ocr 最适用于满足以下条件的字符图像:

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

  • 输入图像应该是黑白的

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

  • 文本行应该是直的

  • 图像应以要检测的文本为中心

(See the tesseract-ocr wiki for further details)

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

根据您提供的输入图像,主要问题是背景噪音过多。为了从图像中的文本中去除背景噪声,我发现应用带有阈值的笔画宽度变换 (SWT) 算法来去除噪声会产生有希望的结果。 libCCV library. 中提供了具有许多可配置参数的 SWT 的快速实现,它对图像的清洁程度取决于许多因素,包括图像大小、笔画宽度的均匀性和算法的其他输入参数。 A list of the configurable parameters is provided here.

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

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

【讨论】:

    【解决方案2】:
    you can use Vision for text detection.
    

    在app 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>
    

    【讨论】:

      猜你喜欢
      • 2015-03-07
      • 1970-01-01
      • 1970-01-01
      • 2021-04-14
      • 2020-01-25
      • 1970-01-01
      • 2021-10-26
      • 1970-01-01
      • 2012-11-17
      相关资源
      最近更新 更多