11

How to get the position of text on the screen in an image using Mobile Vision API, and how to draw a rectangle around them?

Example:

enter image description here

VINNUSAURUS
  • 1,518
  • 3
  • 18
  • 38
  • In the returned `Text` you can pull the components and that include the "bounding boxes", Google has a CodeLab with this exact example, just need to translate it to C# https://codelabs.developers.google.com/codelabs/mobile-vision-ocr/#6 – SushiHangover Nov 04 '18 at 14:24
  • ok will check now. – VINNUSAURUS Nov 04 '18 at 14:35
  • GraphicOverlay is a class in the sample, it just extends View (via the GraphicOverlay.Graphic abstract class), I believe, been awhile since I referenced it to use Mobile Vision in Xamarin (FYI: If this is new code that you are writing, you might want to look at "ML Kit" as it has replaced the Mobile Vision APIs from Google) – SushiHangover Nov 04 '18 at 15:49
  • ok i will get TextBlock info by getBoundingBox() method, will the below code work just by implementing in c# public void draw(Canvas canvas) { if (text == null) { return; } RectF rect = new RectF(text.getBoundingBox()); rect = translateRect(rect); canvas.drawRect(rect, rectPaint); – VINNUSAURUS Nov 04 '18 at 16:18
  • and that ML Kit is specially for android studio developers i think, and Mobile vision API is free as far as i know – VINNUSAURUS Nov 04 '18 at 16:34
  • ML.Kit on device processing is "free" just like M.Vision, the higher accuracy cloud services, like the OCR/Text recognizers, are a billed Firebase service as they are not limited to the mobile optimized ML models and the Android/iOS APIs work fine w/ Xamarin. – SushiHangover Nov 04 '18 at 17:01
  • Does it have c# libraries ? – VINNUSAURUS Nov 04 '18 at 17:10
  • I got three versions can u say which is free version https://cloud.google.com/vision/docs/detecting-text#vision-text-detection-java , https://firebase.google.com/docs/ml-kit/android/recognize-text ,https://codelabs.developers.google.com/codelabs/mobile-vision-ocr/#0 – VINNUSAURUS Nov 04 '18 at 17:21
  • Under ML Kit : https://firebase.google.com/pricing/ – SushiHangover Nov 04 '18 at 17:23
  • so confusing lol. anyway, as long as I use to detect anything that is on the local device it is free? (no free access to cloud version anyway i think ) – VINNUSAURUS Nov 04 '18 at 17:52
  • 1
    ML.Kit : Local = free, Cloud = $ – SushiHangover Nov 04 '18 at 17:53
  • ya but i cannot see c# implementation of it, can u look at this page an say if it is ML Kit version or not https://cloud.google.com/vision/docs/detecting-text – VINNUSAURUS Nov 04 '18 at 17:55

1 Answers1

8

How to do it

Put an ImageView in the layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
    android:layout_width="match_parent"
    android:layout_height="250.0dp"
    android:minWidth="25px"
    android:minHeight="25px"
    android:id="@+id/imageView1" />
</LinearLayout>

Instantiate ImageView in onCreate Method

ImageView imgView;
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.activity_main);

        imgView = FindViewById<ImageView>(Resource.Id.imageView1);
        OCR();
    }

THIS IS IMPORTANT CODE FOR GETTING TEXT AND DRAWING RECTANGLE ON IT

Please read Comments on top of code

public void OCR()
    {
        //Convert The Image To Bitmap
        Bitmap bitmap = BitmapFactory.DecodeResource(ApplicationContext.Resources, Resource.Mipmap.lineindent);

        TextRecognizer textRecognizer = new TextRecognizer.Builder(ApplicationContext).Build();

        if (!textRecognizer.IsOperational)
        {

            Log.Error("Main Activity", "Dependencies not available");

            // Check android for low storage so dependencies can be loaded, DEPRICATED CHANGE LATER
            IntentFilter intentLowStorage = new IntentFilter(Intent.ActionDeviceStorageLow);

            bool hasLowStorage = RegisterReceiver(null, intentLowStorage) != null;

            if (hasLowStorage)
            {

                Toast.MakeText(this, "Low Memory On Disk", ToastLength.Long);
                Log.Error("Main Activity", "Low Memory On Disk");
            }

        }
        else
        {
            Frame frame = new Frame.Builder().SetBitmap(bitmap).Build();


            SparseArray items = textRecognizer.Detect(frame);
            List<TextBlock> blocks = new List<TextBlock>();

            TextBlock myItem = null;
            for (int i = 0; i < items.Size(); ++i)
            {
                myItem = (TextBlock)items.ValueAt(i);

                //Add All TextBlocks to the `blocks` List
                blocks.Add(myItem);

            }
            //END OF DETECTING TEXT

            //The Color of the Rectangle to Draw on top of Text
            Paint rectPaint = new Paint();
            rectPaint.Color = Color.White;
            rectPaint.SetStyle(Paint.Style.Stroke);
            rectPaint.StrokeWidth = (4.0f);

            //Create the Canvas object,
            //Which ever way you do image that is ScreenShot for example, you 
            //need the views Height and Width to draw recatngles 
            //because the API detects the position of Text on the View
            //So Dimesnions are important for Draw method to draw at that Text 
            //Location
            Bitmap tempBitmap = Bitmap.CreateBitmap(bitmap.Width, bitmap.Height, Bitmap.Config.Rgb565);
            Canvas canvas = new Canvas(tempBitmap);
            canvas.DrawBitmap(bitmap, 0, 0, null);

            //Loop through each `Block`
            foreach (TextBlock textBlock in blocks)
            {
                IList<IText> textLines = textBlock.Components; 

                //loop Through each `Line`
                foreach (IText currentLine in textLines)
                {
                    IList<IText>  words = currentLine.Components;

                    //Loop through each `Word`
                    foreach (IText currentword in words)
                    {
                        //Get the Rectangle/boundingBox of the word
                        RectF rect = new RectF(currentword.BoundingBox);
                        rectPaint.Color = Color.Black;

                        //Finally Draw Rectangle/boundingBox around word
                        canvas.DrawRect(rect, rectPaint);

                        //Set image to the `View`
                        imgView.SetImageDrawable(new BitmapDrawable(Resources, tempBitmap));


                    }

                }
            }

        }
    }

RESULT

enter image description here

If you want the Rectangle on Lines then remove the code from words loops and put it in the Lines loop, same goes to the blocks

enter image description here

VINNUSAURUS
  • 1,518
  • 3
  • 18
  • 38