Android Example OCR OFFLINE - Tesseract

I'm working in a project that needs OCR offline. Made a small progress and decided to share here and get some feedback.
I've searched a little bit at this forum and google about it. Found options to use online OCR (NJDUDE's Lib or Erel's example). In the same project I also needs to manipulate some images and got DrewG Exemple about inline code to use JAVACV/OPENCV. This was the point to test Tesseract OCR in the same way (Inline code).
Downloaded the Lib at this link https://repo1.maven.org/maven2/org/bytedeco/javacpp-presets/1.0/javacpp-presets-1.0-bin.zip
More details about this can be found here.

Unzipped and copied the files I needed to my Additional Lib Folder.
The files I used: javacpp.jar, tesseract-android-arm.jar, leptonica-android-arm.jar, tesseract.jar, leptonica.jar

Coded Basic Example from bytedeco page. Made some changes to send the image as a file path to the image saved somewhere in the phone and got the "translation" text.

OBS: I needed to download tessdata files to my cell. Tried to add them to my app, but they were too big and I got some error deploying my app to cell (need to see this more carefully). The files to many languages can be found here or at google project page. I have download this one for my test example.

Here is the code I used. My test phone is a S4.

Hope it helps.
 

Attachments

  • tessTest.zip
    11.9 KB · Views: 1,298
Last edited:

joilts

Member
Licensed User
hello joilts, or Picasso used to trasfomare the image and tesseract ocr for riconoscimeto of letters and numbers with no success, if you can help me with some examples to you already, but unfortunately not familiar java vb net.
greetings Roberto
Roberto, I do not have permission to share the code for this project, but you can find examples at Internet as here. For more details about the javaccp libraries, you can access this link.
Here is a sample code I found at internet (unfortunately I do not have the original link):
B4X:
IplImage grayImg = cvCreateImage(cvGetSize(orgImg),orgImg.depth(),1);
            cvCvtColor(orgImg,grayImg,CV_BGR2GRAY);
cvThreshold(grayImg,grayImg,127, 255, CV_THRESH_OTSU+CV_THRESH_BINARY);   
cvErode(grayImg,grayImg,null,1);
cvDilate(grayImg,grayImg,null,1);

Hope it helps.
 

joilts

Member
Licensed User
thanks for your time, unfortunately not familiar java, thanks anyway
Unfortunately my solution was based on inline java code. I wrote a sample to encapsulate transformation functions in a b4a class. See if it helps a little. You have to save image in same place at device and send image path, name, extension and a name for the image to be saved after transformation. It´s an exemple and the best solution looking for performance is to create a single method to do all transformations U need and avoid many reads and saves. I had no time to test this code (sorry for that).
B4X:
Sub Class_Globals
   
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize

End Sub


Public Sub GrayImage(dir As String, fileName As String, extension As String, newFileName As String)
     Private NativeMe As JavaObject
Try
Try
        NativeMe.InitializeContext
        File.Copy(dir,fileName&extension,global.dir, "1_"&fileName&extension)
        Dim path As String = dir
        Dim name As String = "/1_"&fileName
        NativeMe.RunMethod("converttoGray",  Array (path,name,extension,global.dir, newFileName ))
Catch
    Log("error")
End Try
Catch
    Log("error")
End Try
End Sub


Public Sub ThesImage(dir As String, fileName As String, extension As String, newFileName As String)
     Private NativeMe As JavaObject
Try
Try
        NativeMe.InitializeContext
        File.Copy(dir,fileName&extension,global.dir, "1_"&fileName&extension)
        Dim path As String = dir
        Dim name As String = "/1_"&fileName
        NativeMe.RunMethod("ThrsholdImage",  Array (path,name,extension,global.dir, newFileName ))
Catch
    Log("error")
End Try
Catch
    Log("error")
End Try
End Sub



Public Sub DilateImage(dir As String, fileName As String, extension As String, newFileName As String)
     Private NativeMe As JavaObject
Try
Try
        NativeMe.InitializeContext
        File.Copy(dir,fileName&extension,global.dir, "1_"&fileName&extension)
        Dim path As String = dir
        Dim name As String = "/1_"&fileName
        NativeMe.RunMethod("DilateImage",  Array (path,name,extension,global.dir, newFileName ))
Catch
    Log("error")
End Try
Catch
    Log("error")
End Try
End Sub

Public Sub ErodeImage(dir As String, fileName As String, extension As String, newFileName As String)
     Private NativeMe As JavaObject
Try
Try
        NativeMe.InitializeContext
        File.Copy(dir,fileName&extension,global.dir, "1_"&fileName&extension)
        Dim path As String = dir
        Dim name As String = "/1_"&fileName
        NativeMe.RunMethod("ErodeImage",  Array (path,name,extension,global.dir, newFileName ))
Catch
    Log("error")
End Try
Catch
    Log("error")
End Try
End Sub



#If JAVA

import static org.bytedeco.javacpp.opencv_core.IplImage;
import static org.bytedeco.javacpp.opencv_core.cvCreateImage;
import static org.bytedeco.javacpp.opencv_core.cvGetSize;
import static org.bytedeco.javacpp.opencv_imgproc.CV_BGR2GRAY;
import static org.bytedeco.javacpp.opencv_imgproc.CV_THRESH_OTSU;
import static org.bytedeco.javacpp.opencv_imgproc.CV_THRESH_BINARY;
import static org.bytedeco.javacpp.opencv_imgproc.CV_THRESH_TRUNC;
import static org.bytedeco.javacpp.opencv_imgproc.CV_THRESH_BINARY_INV;
import static org.bytedeco.javacpp.opencv_imgproc.cvThreshold;
import static org.bytedeco.javacpp.opencv_imgproc.cvCvtColor;
import static org.bytedeco.javacpp.opencv_imgproc.cvErode;
import static org.bytedeco.javacpp.opencv_imgproc.cvDilate;
import org.bytedeco.javacpp.BytePointer;
import static org.bytedeco.javacpp.lept.PIX;
import static org.bytedeco.javacpp.lept.pixRead;
import static org.bytedeco.javacpp.lept.pixDestroy;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvLoadImage;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvSaveImage;



public static void converttoGray(String path, String filename, String extension, String result_name) {
        IplImage orgImg = new IplImage();
        orgImg = cvLoadImage(""+path+filename+extension);
        if (orgImg != null) {
            IplImage grayImg = cvCreateImage(cvGetSize(orgImg),orgImg.depth(),1);
            cvCvtColor(orgImg,grayImg,CV_BGR2GRAY);
            cvSaveImage(path+result_name+extension, grayImg);
        }
}


public static void ThrsholdImage(String path, String filename, String extension, String result_name) {
        IplImage orgImg = new IplImage();
        orgImg = cvLoadImage(""+path+filename+extension);
        if (orgImg != null) {
            IplImage grayImg = cvCreateImage(cvGetSize(orgImg),orgImg.depth(),1);
            //Threshold binary
            cvThreshold(grayImg,grayImg,127, 255, CV_THRESH_OTSU+CV_THRESH_BINARY);    
            cvSaveImage(path+result_name+extension, grayImg);
        }
}

public static void ErodeImage(String path, String filename, String extension, , String result_name) {
        IplImage orgImg = new IplImage();
        orgImg = cvLoadImage(""+path+filename+extension);
        if (orgImg != null) {
            IplImage grayImg = cvCreateImage(cvGetSize(orgImg),orgImg.depth(),1);
            cvErode(grayImg,grayImg,null,1);
            cvSaveImage(path+result_name+extension, grayImg);
        }
}

public static void DilateImage(String path, String filename, String extension, , String result_name) {
        IplImage orgImg = new IplImage();
        orgImg = cvLoadImage(""+path+filename+extension);
        if (orgImg != null) {
            IplImage grayImg = cvCreateImage(cvGetSize(orgImg),orgImg.depth(),1);
            cvDilate(grayImg,grayImg,null,1);
            cvSaveImage(path+result_name+extension, grayImg);
        }
}

#END IF
 

roberto64

Active Member
Licensed User
hello joilts, bad value B4A version: 6.31
Parsing code. (0.01s)
Compiling code. (0.11s)
Compiling code layouts. (0.01s)
Organizing libraries. (0.00s)
Generating R files. (0.14s)
Compiling code debugger engine. (2.06s)
Compiling generated Java code. error
javac 1.8.0_102
src \ B4A \ example \ immaginecls.java: 283: error: illegal start of type
public static void ErodeImage (String path, String filename, String extension,, String result_name) {
^
1 error
and also
public static void DilateImage (String path, String filename, String extension,, String result_name) {
IplImage orgImg IplImage = new ();
orgImg = cvLoadImage ( "" + path + filename + extension);
if (orgImg! = null) {
IplImage grayImg = cvCreateImage (cvGetSize (orgImg), orgImg.depth (), 1);
cvDilate (grayImg, grayImg, null, 1);
cvSaveImage (path + result_name + extension, grayImg);
}
}


thanks for your help
 

roberto64

Active Member
Licensed User
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
Error occurred on line: 18 (Immaginecls)
java.lang.RuntimeException: Method: converttoGray not found in: b4a.example.main
at anywheresoftware.b4j.object.JavaObject$MethodCache.getMethod(JavaObject.java:366)
at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:119)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4a.shell.Shell.runVoidMethod(Shell.java:753)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:343)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:247)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:157)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:153)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:78)
at android.view.View.performClick(View.java:4639)
at android.view.View$PerformClick.run(View.java:19252)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5511)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
at dalvik.system.NativeStart.main(Native Method)
 

joilts

Member
Licensed User
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
Error occurred on line: 18 (Immaginecls)
java.lang.RuntimeException: Method: converttoGray not found in: b4a.example.main
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
at dalvik.system.NativeStart.main(Native Method)

Here is a sample project running. Did some fixes to the code I sent before. You will need to find the right parameters to work with images you use.
 

Attachments

  • transformSample.zip
    110.1 KB · Views: 328
Last edited:

roberto64

Active Member
Licensed User
thanks for your time, in the compilation tells me that "the program and was arrested" on my device
thank you
 

roberto64

Active Member
Licensed User
hi, by running the program on my smartphone, see image,
regards
 

Attachments

  • Screenshot_2016-12-02-20-46-16.png
    Screenshot_2016-12-02-20-46-16.png
    111.4 KB · Views: 284

joilts

Member
Licensed User
hi, by running the program on my smartphone, see image,
regards
Roberto, unfortunately I do not understand Italian (my native language is Portuguese), but I tried to google this message and got some links with "Soluzione" attached, like this one. Are you using an Samsung Device with Knox? When searched the message in english, got many links indicating that Knox may be a motive. But as told before, I can be totally wrong in my Italian interpretation.
 
Last edited:

roberto64

Active Member
Licensed User
jolts I have installed on my Samsung device with Knox, I can not understand the problem later with another smatphone'll try and see if you encounter the same problem.
regards
 

roberto64

Active Member
Licensed User
joilts problem is not solved even with other smartphones that mistake, I think the problem and the java code,
greetings and thanks
 

joilts

Member
Licensed User
joilts problem is not solved even with other smartphones that mistake, I think the problem and the java code,
greetings and thanks
I executed this project with no errors on my S4 (without knox) and on my Xperia Z3 compact. I have tested JavaCode also at Android Studio. Unfortunately I have no idea why it does not works to you. The only thing I can came up is that we are not using the same version of javaccp libs. If you wanna try one more time, I have uploaded my Additional Libs Folder to this link. This can be the problem.
 

roberto64

Active Member
Licensed User
joilts thanks for your time you are great works fine thank you very much excuse me for my English.
 

roberto64

Active Member
Licensed User
hello, I run your script but as you see the picture that I see are so.
thank you
 

Attachments

  • images_gray_thes.jpg
    images_gray_thes.jpg
    944 bytes · Views: 207
  • images.jpg
    images.jpg
    9.9 KB · Views: 239
  • images_gray.jpg
    images_gray.jpg
    19.3 KB · Views: 233
  • images_erode.jpg
    images_erode.jpg
    944 bytes · Views: 246
  • images_dilate.jpg
    images_dilate.jpg
    944 bytes · Views: 218
  • 1_images.jpg
    1_images.jpg
    9.9 KB · Views: 272

joilts

Member
Licensed User
hello, I run your script but as you see the picture that I see are so.
thank you
You need to test and find the right parameters for the transformations you need. At my example, I took random values to dilate an erode. You need to find the right values and combine them to get the best and clean black and with image to your images. Here is an example of a Brazilian plate I got from internet. original_image.jpg final_image.jpg
 

roberto64

Active Member
Licensed User
I can not understand what the values to change, what part of the code, I tried in vain to change the code on the routines of java "DilateImage" and "ErodeImage"
thank you
 

joilts

Member
Licensed User
I can not understand what the values to change, what part of the code, I tried in vain to change the code on the routines of java "DilateImage" and "ErodeImage"
thank you
Unfortunately I can´t help you with this. I tested your image with some different configurations and got something near to what you going to need. Try this settings and try to change values to them. imagem1.jpg base_pict.jpg

B4X:
IplImage grayImg = cvCreateImage(cvGetSize(orgImg),orgImg.depth(),1);
cvCvtColor(orgImg,grayImg,CV_BGR2GRAY);
cvThreshold(grayImg,grayImg,127, 255, CV_THRESH_OTSU+CV_THRESH_BINARY);    
cvErode(grayImg,grayImg,null,1);
cvDilate(grayImg,grayImg,null,1);
cvSaveImage(path+"/base_pict"+extension, grayImg);
 

roberto64

Active Member
Licensed User
I thank you for your disponibiltà and the time you're losing me, I tried your routines is fine to do the image B & W, realizing edesso comene works that I can put inside other commands in rurine fact I added "IplConvKernel mat = cvCreateStructuringElementEx (5, 5, 2, 2, CV_SHAPE_RECT);
cvErode (grayImg, grayImg, mat, 1); so I more black letters and numbers, but I noticed that tessdata OCR does not recognize well the numbers and sometimes letters.
I thank you you're great.
 
Top