B4A Library OCR - MobileVisionText

This is a "shortcut" wrap for this project. I have zipped the complete B4A project (and it includes the aar, jar, and xml files). Copy the aar, jar, and xml files to your additional library folder.

The zipped project is here:
https://drive.google.com/file/d/0B4g9tud5lvjgSHE3VFc0aEZjUHc/view?usp=sharing

Libraries enabled:
Libraries.png



Take note of the B4A manifest file:
B4X:
'This code will be applied to the manifest file during compilation.
'You do not need to modify it in most cases.
'See this link for for more information: https://www.b4x.com/forum/showthread.php?p=78136
AddManifestText(
<uses-sdk android:minSdkVersion="5" android:targetSdkVersion="22"/>
<supports-screens android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true"
    android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
'End of default text.

SetApplicationAttribute(android:theme, "@style/MyAppTheme")
AddApplicationText(<meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
        <meta-data
            android:name="com.google.android.gms.vision.DEPENDENCIES"
            android:value="ocr" />

<activity android:name="com.truiton.mobile.vision.ocr.MainActivity">

        </activity>)

Take note of the "resource" and "DemoRes" folders and contents that are on the same folder level as that of the B4A project's /Files and /Objects folders

What does this project do?
1. It starts the native camera
2. Take a photo of text
3. Save or discard the photo taken that has the text
3. If (3) = Save it returns the Blocks, Lines, and Words identified in the picture to the B4A project via events else it starts the camera again for you to take another photo of text.


Sample B4A code:
B4X:
#Region  Project Attributes
    #ApplicationLabel: b4aMobileVisionText
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: landscape
    #CanInstallToExternalStorage: False
#End Region

#AdditionalRes: ..\DemoRes
#AdditionalRes: ..\resource


#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Dim mvt As MobileVisionText

    Private Button1 As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("main")

    mvt.Initialize("mvt")

End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub


Sub Button1_Click

    mvt.startMobileVisionText

End Sub

Sub mvt_blocks_result(blocks As String)

    Log("B4A Blocks = " & blocks)

End Sub

Sub mvt_lines_result(lines As String)

    Log("B4A Lines = " & lines)

End Sub

Sub mvt_words_result(words As String)

    Log("B4A Words = " & words)

End Sub

Sub mvt_error_result(error As String)

    Log("B4A ERROR = " & error)

End Sub

Have done this with B4A V6.80 and on a KitKat device.

Library:
MobileVisionText
Version:
1
MobileVisionText
Events:

  • blocks_result (blocks As String)
  • error_result (error As String)
  • lines_result (lines As String)
  • words_result (words As String)
Methods:
  • Initialize (paramString As String)
  • IsInitialized As Boolean
  • startMobileVisionText
Permissions:
  • android.permission.CAMERA
  • android.permission.WRITE_EXTERNAL_STORAGE

To compile the Java code setup:
1. Create a libs folder on the same level as that of the src folder
2. Copy android-support-v4.jar, android-support-v7-appcompat.jar, constraint-layout-1.0.1.jar, and play-services-vision-9.4.0.jar into the libs folder that you have created.
 

Attachments

  • TheJavaCode.zip
    5 KB · Views: 666
Last edited:

wes58

Active Member
Licensed User
Longtime User
I have tried your library and it works perfect. The only issue I have (not your fault) is that when I wanted to scan text in portrait, I didn't get any text. And the reason was that the saved picture is rotated (saved in landscape mode).
To fix my problem easily (not perfect solution, I think) I compiled your library java code with the following changes:
1. check the screen orientation
2. rotate the bitmap
B4X:
    public static Bitmap rotate(Bitmap bitmap, int degree) {
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        Matrix mtx = new Matrix();
        mtx.postRotate(degree);
        return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
    }   

    private Bitmap decodeBitmapUri(Context ctx, Uri uri) throws FileNotFoundException {
 
          int targetW = 600;
        int targetH = 600;
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(ctx.getContentResolver().openInputStream(uri), null, bmOptions);
        int photoW = bmOptions.outWidth;
        int photoH = bmOptions.outHeight;
        int scaleFactor = Math.min(photoW / targetW, photoH / targetH);
        bmOptions.inJustDecodeBounds = false;
        bmOptions.inSampleSize = scaleFactor;
        Bitmap bm = BitmapFactory.decodeStream(ctx.getContentResolver().openInputStream(uri), null, bmOptions);
        int rotation = this.getWindowManager().getDefaultDisplay().getRotation();
        if(rotation == 0){    //portrait
            rotation = 90;
        }
        else if(rotation == 1){        //landscape
            rotation = 0;
        }
        else if(rotation == 2){   
            rotation = 270;
        }
        else if(rotation == 3){
            rotation = 180;
        }
        bm = rotate(bm, rotation);
        return bm;
    }
I hope that it may be useful to someone. There are probably better solution to detect the orientation of the taken photo, but for me on Galaxy S7 it works fine.
 

Johan Schoeman

Expert
Licensed User
Longtime User
I have tried your library and it works perfect. The only issue I have (not your fault) is that when I wanted to scan text in portrait, I didn't get any text. And the reason was that the saved picture is rotated (saved in landscape mode).
To fix my problem easily (not perfect solution, I think) I compiled your library java code with the following changes:
1. check the screen orientation
2. rotate the bitmap
B4X:
    public static Bitmap rotate(Bitmap bitmap, int degree) {
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        Matrix mtx = new Matrix();
        mtx.postRotate(degree);
        return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
    }

    private Bitmap decodeBitmapUri(Context ctx, Uri uri) throws FileNotFoundException {

          int targetW = 600;
        int targetH = 600;
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(ctx.getContentResolver().openInputStream(uri), null, bmOptions);
        int photoW = bmOptions.outWidth;
        int photoH = bmOptions.outHeight;
        int scaleFactor = Math.min(photoW / targetW, photoH / targetH);
        bmOptions.inJustDecodeBounds = false;
        bmOptions.inSampleSize = scaleFactor;
        Bitmap bm = BitmapFactory.decodeStream(ctx.getContentResolver().openInputStream(uri), null, bmOptions);
        int rotation = this.getWindowManager().getDefaultDisplay().getRotation();
        if(rotation == 0){    //portrait
            rotation = 90;
        }
        else if(rotation == 1){        //landscape
            rotation = 0;
        }
        else if(rotation == 2){
            rotation = 270;
        }
        else if(rotation == 3){
            rotation = 180;
        }
        bm = rotate(bm, rotation);
        return bm;
    }
I hope that it may be useful to someone. There are probably better solution to detect the orientation of the taken photo, but for me on Galaxy S7 it works fine.
I have no problem should you want to post your updated library for other members to use. Thanks for the update/changes/sharing your mods
 
Last edited:

jarinashameem

Member
Licensed User
Longtime User
Hi,
When used the sample code, there is a error as mentioned below.

B4A ERROR = Could not set up the detector!

Please provide the solution
 

Johan Schoeman

Expert
Licensed User
Longtime User
If you don't initially have an active internet connection the dependencies won't be downloaded and then the detector won't work. I guess that is perhaps the problem that you have at present i.e the dependencies have not been installed on your device (it should happen automatically when you start the app with an active internet connection)
 

jarinashameem

Member
Licensed User
Longtime User
Sorry, i tried using both Data Connection and WiFi Connected Internet. I am getting this error on the log

Logger connected to: LENOVO Lenovo A7010a48
--------- beginning of system
--------- beginning of main
sending message to waiting queue (mvt_error_result)
sending message to waiting queue (OnActivityResult)
running waiting messages (2)
B4A ERROR = Could not set up the detector!
** Activity (main) Resume **
 

Johan Schoeman

Expert
Licensed User
Longtime User
For some reason your detector is not active. I guess it is because the dependencies have not downloaded and installed successfully.


B4X:
                if (detector.isOperational() && bitmap != null) {
                    Frame frame = new Frame.Builder().setBitmap(bitmap).build();
                    SparseArray<TextBlock> textBlocks = detector.detect(frame);
                    String blocks = "";
                    String lines = "";
                    String words = "";
                    for (int index = 0; index < textBlocks.size(); index++) {
                        //extract scanned text blocks here
                        TextBlock tBlock = textBlocks.valueAt(index);
                        blocks = blocks + tBlock.getValue() + "\n" + "\n";
                        for (Text line : tBlock.getComponents()) {
                            //extract scanned text lines here
                            lines = lines + line.getValue() + "\n";
                            for (Text element : line.getComponents()) {
                                //extract scanned text words here
                                words = words + element.getValue() + ", ";
                            }
                        }
                    }
                    if (textBlocks.size() == 0) {
                        scanResults.setText("Scan Failed: Found nothing to scan");
                    } else {
                        scanResults.setText(scanResults.getText() + "Blocks: " + "\n");
                        scanResults.setText(scanResults.getText() + blocks + "\n");
                        scanResults.setText(scanResults.getText() + "---------" + "\n");
                        scanResults.setText(scanResults.getText() + "Lines: " + "\n");
                        scanResults.setText(scanResults.getText() + lines + "\n");
                        scanResults.setText(scanResults.getText() + "---------" + "\n");
                        scanResults.setText(scanResults.getText() + "Words: " + "\n");
                        scanResults.setText(scanResults.getText() + words + "\n");
                        scanResults.setText(scanResults.getText() + "---------" + "\n");
                    }
                } else {
                    scanResults.setText("Could not set up the detector!");
                }
 

supriono

Member
Licensed User
Longtime User
i have this error
can same one help me how to fixe this?

B4A Version: 8.00
Parsing code. (0.01s)
Compiling code. (6.03s)
Compiling layouts code. (0.01s)
Organizing libraries. (18.52s)
Generating R file. (14.44s)
Compiling generated Java code. (32.45s)
Convert byte code - optimized dex. Error
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/truiton/mobile/vision/ocr/MainActivity;
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/truiton/mobile/vision/ocr/MainActivity$1;
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/truiton/mobile/vision/ocr/R;
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/truiton/mobile/vision/ocr/R$id;
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/truiton/mobile/vision/ocr/R$layout;
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lmobilevisiontextwrapper/mobilevisiontextWrapper;
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lmobilevisiontextwrapper/mobilevisiontextWrapper$1;
7 errors; aborting
 
Top