最近做公司的一个新的项目,需要实现图片内容的识别,经过百度很多都是使用opencv和tess-two实现的,自己跟着操作,记录下实现的过程和一些代码。
opencv和tess-two都是第三方库,需要自己添加依赖,tess-two的依赖添加很简单,在项目的build.gradle文件下添加外部依赖就可以了例如:implementation 'com.rmtheis:tess-two:6.1.1' 这样就可以添加tess-two的依赖的,但是opencv的依赖就不是这样的了,需要去下载相关的文件,opencv 下载链接,下载页面还有简单的引入教程,这里也简单的说下自己的引入步骤:
1、下载opencv-2.4.11-android-sdk.zip,并解压,解压后的文件目录结构是:
2、打开目录下的sdk文件夹:将sdk文件夹下的java文件夹导入到项目中,as的导入流程是:
file ----> new -----> Import Module ,这样就可以导入到项目中,这个过程可能有错误出现,修改构建sdk版本好就可以解决。
3、在项目的app/src/main 目录下创建一个jniLibs目录,将 sdk/native 下的所有文件都拷贝到jniLibs的目录下。
上面三步就完成了opencv的导入。至于如何使用就不细说了,说一下使用过程中遇到的问题:
在使用的过程中没有初始化opencv,会报错,找不到native 的方法,这里需要注意一下,可以使用initdebug()这个方法或这initsync()这个方法来初始化。
package com.example.lucrazy.opencvproject.utils;
import android.graphics.Bitmap;
import android.os.Environment;
import android.util.Log;
import com.googlecode.tesseract.android.TessBaseAPI;
import org.opencv.android.Utils;
import org.opencv.core.CvException;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Tesscv {
private final static String TAG="tesscv";
Bitmap m_phone;
TessBaseAPI m_tessApi;
String m_datapath;
String m_lang = "eng";
InputStream m_instream;
public Tesscv(InputStream instream) {
this.m_instream = instream;
m_datapath = Environment.getExternalStorageDirectory() + File.separator + "tesseract/";
checkFile(new File(m_datapath+"tessdata/"));
m_tessApi = new TessBaseAPI();
m_tessApi.init(m_datapath,m_lang);
}
public void setM_phone(Bitmap m_phone){
this.m_phone = m_phone;
}
private void saveTmpImage(String name, Mat image) {
Mat img = image.clone();
if (img.channels() ==3 ) {
Imgproc.cvtColor(img, img, Imgproc.COLOR_BGR2RGBA);
}
Bitmap bmp = null;
try {
bmp = Bitmap.createBitmap(img.cols(), img.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(img, bmp);
} catch (CvException e) {
Log.d("mat2bitmap", e.getMessage());
}
File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "MyLibApp/tesscv");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("saveTmpImage", "failed to create directory");
return;
}
}
//String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
//File dest = new File(mediaStorageDir.getPath() + File.separator + name + timeStamp + ".png");
File dest = new File(mediaStorageDir.getPath() + File.separator + name + ".png");
FileOutputStream out = null;
try {
out = new FileOutputStream(dest);
bmp.compress(Bitmap.CompressFormat.PNG, 100, out);
// bmp is your Bitmap instance
// PNG is a lossless format, the compression factor (100) is ignored
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Long time;
public String getOcrOfBitmap() {
if (m_phone == null) {
return "";
}
time = System.currentTimeMillis();
Log.d(TAG,"start-------------");
Mat imgBgra = new Mat(m_phone.getHeight(), m_phone.getWidth(), CvType.CV_8UC4);
// Mat imgBgra = new Mat();
Utils.bitmapToMat(m_phone, imgBgra);
Mat imgBgr = new Mat();
Imgproc.cvtColor(imgBgra, imgBgr, Imgproc.COLOR_RGBA2BGR);
Mat img = imgBgr;
// saveTmpImage("srcInputBitmap", img);
if (img.empty()) {
return "";
}
if (img.channels()==3) {
Imgproc.cvtColor(img, img, Imgproc.COLOR_BGR2GRAY);
}
return getResOfTesseractReg(img);
}
private String getResOfTesseractReg(Mat img) {
String res;
if (img.empty()) {
return "";
}
byte[] bytes = new byte[(int)(img.total()*img.channels())];
img.get(0, 0, bytes);
m_tessApi.setImage(bytes, img.cols(), img.rows(), 1, img.cols());
res = m_tessApi.getUTF8Text();
Log.d(TAG,"end---------------- "+(System.currentTimeMillis()-time));
Log.d(TAG,"result "+res);
String[] strins = res.split("\n");
for (String string:strins){
Log.d(TAG,"string "+string);
}
return res;
}
private void checkFile(File dir) {
//directory does not exist, but we can successfully create it
if (!dir.exists() && dir.mkdirs()){
copyFiles();
}
//The directory exists, but there is no data file in it
if(dir.exists()) {
String datafilepath = dir.toString() + "/eng.traineddata";
File datafile = new File(datafilepath);
if (!datafile.exists()) {
copyFiles();
}
}
}
private void copyFiles() {
try {
if (m_instream == null) {
//TODO
String resInPath = "/tessdata/eng.traineddata";
//Log.d(TAG, "copyFiles: resInPath " + resInPath);
m_instream = new FileInputStream(resInPath);
}
//location we want the file to be a
String resOutPath = m_datapath + "/tessdata/eng.traineddata";
//open byte streams for writing
OutputStream outstream = new FileOutputStream(resOutPath);
//copy the file to the location specified by filepath
byte[] buffer = new byte[1024];
int read;
while ((read = m_instream.read(buffer)) != -1) {
outstream.write(buffer, 0, read);
}
outstream.flush();
outstream.close();
m_instream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}