I am not much of an expert.I am using tesseract (tess-two) for developing an android application for my college project. The application crashes when I select the Nepali trained data.
*The application works only with Image selected from gallery. The image taken from camera returns empty result. So, yes! I am in big trouble here!!
Here is the snippet of the LogCat when I used eng.trainddata:
04-26 22:52:02.286 26503-26509/com.l.android.neptext I/zygote64: Do partial code cache collection, code=124KB, data=69KB
After code cache collection, code=124KB, data=69KB
Increasing code cache capacity to 512KB
04-26 22:52:02.347 26503-26520/com.l.android.neptext I/vndksupport: sphal namespace is not configured for this process. Loading /vendor/lib64/hw/gralloc.msm8996.so from the current namespace instead.
04-26 22:52:08.559 26503-26503/com.l.android.neptext D/com.l.android.neptext.MainActivity$3@2314718: onClick:
04-26 22:52:08.612 26503-26503/com.l.android.neptext D/AppTracker: App Event: stop
04-26 22:52:21.431 26503-26503/com.l.android.neptext D/AppTracker: App Event: start
04-26 22:52:21.603 26503-26589/com.l.android.neptext I/com.l.android.neptext.MainActivity$5@8074bd5: bitmap size8294400
04-26 22:52:22.232 26503-26589/com.l.android.neptext I/Tesseract(native): Initialized Tesseract API with language=eng
04-26 22:52:35.031 26503-26509/com.l.android.neptext I/zygote64: Compiler allocated 6MB to compile void android.view.ViewRootImpl.performTraversals()
04-26 22:52:39.452 26503-26503/com.l.android.neptext D/AppTracker: App Event: stop
Another snippet when I use nep.traineddata:
04-26 22:53:44.007 26764-26769/com.l.android.neptext I/zygote64: Compiler allocated 6MB to compile void android.view.ViewRootImpl.performTraversals()
04-26 22:53:44.095 26764-26780/com.l.android.neptext D/OpenGLRenderer: endAllActiveAnimators on 0x7e841e2000 (DropDownListView) with handle 0x7e7abf6840
04-26 22:53:46.978 26764-26764/com.l.android.neptext D/com.l.android.neptext.MainActivity$3@cc3f660: onClick:
04-26 22:53:47.033 26764-26764/com.l
.android.neptext D/AppTracker: App Event: stop
04-26 22:54:00.276 26764-26764/com.l.android.neptext D/AppTracker: App Event: start
04-26 22:54:00.449 26764-26815/com.l.android.neptext I/com.l.android.neptext.MainActivity$5@c8be754: bitmap size8294400
The app crashes without other error message.
Code of Project:
public class MainActivity extends AppCompatActivity {
public static Button camera,gallery,cut,copy,speech;
public static EditText text;
public static TextView textView;
public static final int GALERY_ACTION=100;
public static final int CAMERA_ACTION=101;
public static Uri imageuri=null;
Handler texthandler;
TextToSpeech t1;
Spinner spinner;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
camera=findViewById(R.id.button1);
gallery=findViewById(R.id.button2);
cut=findViewById(R.id.cut_btn);
copy=findViewById(R.id.copy_btn);
speech=findViewById(R.id.speech_btn);
text = findViewById(R.id.result_text);
textView=findViewById(R.id.textView);
spinner=findViewById(R.id.spinner);
spinner=findViewById(R.id.spinner);
List<String> categories = new ArrayList<String>();
categories.add("eng");
categories.add("nep");
// Creating adapter for spinner
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, categories);
// Drop down layout style - list view with radio button
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// attaching data adapter to spinner
spinner.setAdapter(dataAdapter);
t1=new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR) {
t1.setLanguage(Locale.UK);
}
}
});
texthandler=new Handler(Looper.myLooper()){
@Override
public void handleMessage(Message msg) {
String t=(String)msg.obj;
if(t==null){
Toast.makeText(getApplicationContext(),"Cannot find any letters ",Toast.LENGTH_LONG).show();
}
text = findViewById(R.id.result_text);
text.setText((String)msg.obj);
}
};
onButtonClickListiner();
//copying tranning datas
try {
MainApplication.instance.copydata("eng");
MainApplication.instance.copydata("nep");
}catch(Exception e){
Log.d("OcrManager",e.getMessage());
}
}
public void copy(View view){
text = findViewById(R.id.result_text);
Log.d(this.toString(),text.getText().toString());
ClipboardManager clipboardManager=(ClipboardManager)getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clipData=ClipData.newPlainText("label",text.getText().toString());
clipboardManager.setPrimaryClip(clipData);
Toast.makeText(MainActivity.this,"Text copied to clipbaord",Toast.LENGTH_LONG).show();
}
public void cut(View view){
text = findViewById(R.id.result_text);
Log.d(this.toString(),text.getText().toString());
ClipboardManager clipboardManager=(ClipboardManager)getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clipData=ClipData.newPlainText("label",text.getText().toString());
clipboardManager.setPrimaryClip(clipData);
text.setText("");
Toast.makeText(MainActivity.this,"Text copied to clipbaord",Toast.LENGTH_LONG).show();
}
public void speech(View view){
text = findViewById(R.id.result_text);
Log.d(this.toString(),text.getText().toString());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
t1.speak(text.getText().toString(),TextToSpeech.QUEUE_FLUSH,null,null);
} else {
t1.speak(text.getText().toString(), TextToSpeech.QUEUE_FLUSH, null);
}
Toast.makeText(this,"Speaking now",Toast.LENGTH_LONG).show();
}
private void onButtonClickListiner(){
gallery.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try{
Log.d(this.toString(), "onClick: ");
Intent galaryIntent=new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI);
startActivityForResult(galaryIntent,GALERY_ACTION);
gallery.setVisibility(View.GONE);
camera.setVisibility(View.GONE);
textView.setVisibility(View.GONE);
cut.setVisibility(View.VISIBLE);
copy.setVisibility(View.VISIBLE);
speech.setVisibility(View.VISIBLE);
text.setVisibility(View.VISIBLE);
spinner.setVisibility(View.GONE);
}catch(Exception e){
Log.d("Main actiity",e.getMessage());
}
}
});
camera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try{
Intent cameraIntent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent,CAMERA_ACTION);
gallery.setVisibility(View.GONE);
camera.setVisibility(View.GONE);
textView.setVisibility(View.GONE);
cut.setVisibility(View.VISIBLE);
copy.setVisibility(View.VISIBLE);
speech.setVisibility(View.VISIBLE);
text.setVisibility(View.VISIBLE);
spinner.setVisibility(View.GONE);
}catch(Exception e){
Log.d("Main actiity",e.getMessage());
}
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
if (resultCode == RESULT_OK && data != null) {
if (requestCode == GALERY_ACTION) {
imageuri = data.getData();
try {
MainApplication.instance.showToast("Rendering Started,Please wait");
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageuri);
Log.i(this.toString(),"bitmap size"+bitmap.getByteCount());
OcrManager ocrManager= new OcrManager();
ocrManager.ocrStart(spinner.getSelectedItem().toString());
final String s = ocrManager.getText(bitmap);
Message m = new Message();
m.obj = s;
texthandler.sendMessage(m);
} catch (Exception e) {
Log.e("Main actiity", e.getMessage());
}
}
}).start();
} catch (Exception e) {
Log.d(this.toString(), e.getMessage());
}
}else if(requestCode==CAMERA_ACTION){
try {
MainApplication.instance.showToast("Rendering Started,Please wait");
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
try {
Bundle bundle=data.getExtras();
Bitmap bitmap = (Bitmap)bundle.get("data");
OcrManager ocrManager= new OcrManager();
ocrManager.ocrStart(spinner.getSelectedItem().toString());
final String s = ocrManager.getText(bitmap);
Message m = new Message();
m.obj = s;
texthandler.sendMessage(m);
} catch (Exception e) {
Log.d("Main actiity", e.getMessage());
}
}
}).start();
} catch (Exception e) {
Log.d(this.toString(), e.getMessage());
}
}
}
}
}
OCRManager Class:
public class OcrManager {
public static TessBaseAPI base=null;
public void ocrStart(String lang) {
try{
base = new TessBaseAPI();
String dataDirectory = MainApplication.instance.tessDataPathParent();
base.init(dataDirectory, lang);
}catch(Exception e){}
}
public String getText(Bitmap bitmap){
base.setImage(bitmap);
MainApplication.instance.showToast("Conversion Started");
String out=base.getUTF8Text();
MainApplication.instance.showToast("Conversion finished");
return out;
}
}
Also there is another class which copies nepali and english trained data to the storage successfully.
So, what am I doing wrong here? There is no any result when camera is used and the app crashes when nepali trained data is used with gallery source. Please help me out here. I do not want to do this again in resit.
So the other thing I had done wrong was the value of dataDirectory and just changing its value made the application a lot stable. The nep.trained data was found and initialized by the tesseract after that.
private static final String dataDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/com.lokensapkota.android.neptext/";
Also, if I changed the whole function in MainApplication class; which was just there to copy the trained data, to a method and ran it in background.:
private void copyAssets() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("trainneddata");
} catch (IOException e) {
Log.e("tag", "Failed to get asset file list.", e);
}
for(String filename : files) {
Log.i("files",filename);
InputStream in = null;
OutputStream out = null;
String dirout= dataDirectory + "tessdata/";
File outFile = new File(dirout, filename);
if(!outFile.exists()) {
try {
in = assetManager.open("trainneddata/"+filename);
(new File(dirout)).mkdirs();
out = new FileOutputStream(outFile);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (IOException e) {
Log.e("tag", "Error creating files", e);
}
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
Even though the the previous MainApplication.class copied both english and nepali trained data to the app directory, the nep.traineddata failed to initialized. this method, however did the same thing but it made things work.