我制作了一个简单的应用程序,用于读取图像并使用android检索数字图像作为文本。但问题是精度仅为60%左右,并且也会出现一些不需要的噪音。我确实认为准确度不可能达到100%,但是,我认为必须有一种方法来改进它。但是,既然我是业余爱好者,我觉得很难。我搜索了谷歌,但无法获得可靠的信息。
我想从东方幸运票中读取数字596,00和012345,如下图所示。
答案 0 :(得分: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,您只需将正则表达式应用于输出即可删除任何最终的错误检测。
答案 1 :(得分:0)
import { Component } from '@angular/core'; import { NavController } from 'ionic-angular'; import { StreamingMedia, StreamingAudioOptions } from '@ionic-native/streaming-media'; @Component({ selector: 'page-home', templateUrl: 'home.html' }) export class HomePage { constructor(public navCtrl: NavController,private streamingMedia: StreamingMedia) {} startAudio(){ let options: StreamingAudioOptions = { successCallback: () => { console.log('Video played') }, errorCallback: (e) => { console.log(JSON.stringify(e,null,2)) }, initFullscreen:false, }; this.streamingMedia.playAudio('YOUR_URL', options); }
在app gradle中添加依赖项
you can use Vision for text detection.
添加Manifest.xml
compile 'com.google.android.gms:play-services-vision:10.0.0'
MainActivity.java
<meta-data
android:name="com.google.android.gms.vision.DEPENDENCIES"
android:value="ocr" />
activity_main.xml中
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;
}
}
}