GhostPoltergeist
GhostPoltergeist

Reputation: 1

Android Application ID OCR with Google MLKI

I am having a hardtime processing this, I want my OCR to be accurate without the usage of Regex I want this MLkit to determine it for me if it is Name, Address, ID number and Nationality if one of that info is not present in the ID then therefore it is considered as N/A but my problem is that it is not accurate, is there any way to improve its accuracy without going to use paid API's or SDK's, I also don't find Regex useful at this type of issue it gives me data inconsistency too.

package com.system.universal_idscanner;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.util.Size;
import android.util.SparseArray;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.google.android.gms.vision.Frame;
import com.google.android.gms.vision.text.TextBlock;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.mlkit.vision.common.InputImage;
import com.google.mlkit.vision.text.TextRecognition;
import com.google.mlkit.vision.text.TextRecognizer;
import com.google.mlkit.vision.text.latin.TextRecognizerOptions;

import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_CAMERA_PERMISSION = 100;
    private PreviewView previewViewer;
    private ImageCapture imageCapture;
    private ExecutorService cameraExecutor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        previewViewer = findViewById(R.id.previewView);
        findViewById(R.id.captureButton).setOnClickListener(v -> captureImage());

        cameraExecutor = Executors.newSingleThreadExecutor();

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
            startCamera();
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
        }
    }

    private void startCamera() {
        ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
        cameraProviderFuture.addListener(() -> {
            try {
                ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
                Preview preview = new Preview.Builder().build();
                CameraSelector cameraSelector = new CameraSelector.Builder()
                        .requireLensFacing(CameraSelector.LENS_FACING_BACK) // Use front camera
                        .build();

                imageCapture = new ImageCapture.Builder()
                        .setTargetResolution(new Size(1920, 1080))
                        .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                        .setJpegQuality(100) // Best quality
                        .build();

                preview.setSurfaceProvider(previewViewer.getSurfaceProvider());
                cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture);

            } catch (Exception e) {
                Log.e("CameraX", "Error starting camera: " + e.getMessage());
            }
        }, ContextCompat.getMainExecutor(this));
    }

    private void captureImage() {
        File file = new File(getExternalFilesDir(null), "captured_image.jpg");
        ImageCapture.OutputFileOptions options = new ImageCapture.OutputFileOptions.Builder(file).build();

        imageCapture.takePicture(options, cameraExecutor, new ImageCapture.OnImageSavedCallback() {
            @Override
            public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
                processImage(file);
            }

            @Override
            public void onError(@NonNull ImageCaptureException exception) {
                Log.e("CameraX", "Error capturing image: " + exception.getMessage());
            }
        });
    }

    private void processImage(File imageFile) {
        Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath());

        // Check image size
        if (bitmap.getWidth() < 720 || bitmap.getHeight() < 1280) {
            //DO SOMETHING
            return;
        }

        // Initialize the Google Play Services ML Kit TextRecognizer
        com.google.android.gms.vision.text.TextRecognizer recognizer =
                new com.google.android.gms.vision.text.TextRecognizer.Builder(this).build();

        if (!recognizer.isOperational()) {
            Log.e("MLKit", "Text recognition dependencies are not yet available.");
            //DO SOMETHING
            return;
        }

        // Process the image
        Frame frame = new Frame.Builder().setBitmap(bitmap).build();
        SparseArray<TextBlock> textBlocks = recognizer.detect(frame);

        StringBuilder extractedText = new StringBuilder();
        for (int i = 0; i < textBlocks.size(); i++) {
            TextBlock textBlock = textBlocks.valueAt(i);
            extractedText.append(textBlock.getValue()).append("\n");
        }

        String result = extractedText.toString().trim();
        if (result.isEmpty()) {
            //DO SOMETHING
        } else {
            // Call extractIDDetails to parse the ID details
            extractIDDetails(result);
        }
    }

    private void extractIDDetails(String text) {
        StringBuilder extractedData = new StringBuilder();
        String[] lines = text.split("\n");

        for (String line : lines) {
            line = line.trim();
            if (!line.isEmpty()) {  // Avoid adding empty lines
                extractedData.append(line).append("\n");
            }
        }

        // Pass extracted details to IDDetailsActivity
        Intent intent = new Intent(this, IDDetailsActivity.class);
        intent.putExtra("extractedData", extractedData.toString());

        runOnUiThread(() -> startActivity(intent)); // Start activity in UI thread
    }
}

Upvotes: 0

Views: 36

Answers (0)

Related Questions