mrOlympia
mrOlympia

Reputation: 351

Android - draw rectangle on uploaded bitmap image

I am using a tflite model and I am trying to draw a RectF on the image where the object is detected.

Here is my CameraActivity.java class where I am detecting the object.

predictBtn.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                img = Bitmap.createScaledBitmap(img, 128, 128, true);

                try {
                    DrawView drawView = new DrawView(getApplicationContext());
                    Android model = Android.newInstance(getApplicationContext());

                    // Creates inputs for reference.
                    TensorImage image = TensorImage.fromBitmap(img);


                    // Runs model inference and gets result.
                    Android.Outputs outputs = model.process(image);
                    Android.DetectionResult detectionResult = outputs.getDetectionResultList().get(0);

                    // Gets result from DetectionResult.
                    float score = detectionResult.getScoreAsFloat();
                    RectF location = detectionResult.getLocationAsRectF();
                    String category = detectionResult.getCategoryAsString();

                    // Releases model resources if no longer used.

                    mCanvas.drawBoundingBox();
                    model.close();
                    // here we will print out the results of the object to text views based on the image that is inputted by the user
                    // we print out object type and its accuracy score
                    mCanvasView.drawRect();
                    objecttv.setText(category);
                    scoretv.setText(Float.toString(score));

                } catch (IOException e) {
                    // TODO Handle the exception
                }

            }
        }
        );

Here is my DrawView.java class

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class DrawView extends View {
    Paint boxPaint;
    public static Canvas mCanvas;

    public DrawView(Context context) {
        super(context);
        boxPaint = new Paint();
    }

    public void drawBoundingBox() {
        // Refresh the view by calling onDraw function
        invalidate();
    }

    
    public void onDraw(Canvas canvas, AttributeSet attrs) {
        // Draw what you want
        boxPaint.setColor(Color.RED);
        boxPaint.setAlpha(200);
        boxPaint.setStyle(Paint.Style.STROKE);
        canvas.drawRect(location, boxPaint);
    }
}

In my activity_camera.xml , I added the drawview to match the image I am uploading.

  <com.example.aPROJECT.DrawView
        android:id="@+id/canvasView"
        android:layout_width="281dp"
        android:layout_height="324dp"
        android:layout_marginTop="30dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
         />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="281dp"
        android:layout_height="324dp"
        android:layout_marginTop="30dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@android:drawable/ic_menu_gallery"
        tools:ignore="ImageContrastCheck" />

In the CameraActivity.java , on line mCanvas.drawBoundingBox(); it cannot access the mCanvas from the DrawView.java class.

On line mCanvasView.drawRect(); it cannot resolve the symbol .

What am I missing here?

Upvotes: 2

Views: 437

Answers (1)

Crispert
Crispert

Reputation: 1167

There are several problems:

  • if you want to access a static field outside of its class in Java you need to either specify the class name like this DrawView.mCanvas or to use a static import (add a line

    import static /*class.package.name.here.*/DrawView.mCanvas;
    

    above the class declaration and then you can use mCanvas directly)

  • drawBoundingBox() is a method in DrawView, not canvas so the correct way to call would be drawView.drawBoundingBox()

  • even if the class would compile you'd get a NullPointerException when drawRoundingBox() was called because mCanvas has not been initialized in DrawView

  • the canvas in a View is only a temporary variable as parameter to onDraw used to create the user interface at that moment in time (each frame) and is not meant to be used outside of that method since it points/refers to a video memory buffer that is continuously changed

What you should do is create a Canvas for the Bitmap you're trying to draw on and use it (you don't need a view to alter a bitmap):

//if img is the bitmap you want to draw on
Canvas c = new Canvas(img); //before createScaledBitmap()
drawBoundingBox(c);// move onDraw code to drawBoundingBox()
                   // and the latter method to CameraActivity

//Should you need to get the bitmap screenshot of a view simply draw it:
Bitmap vscr = Bitmap.createBitmap(yourView.getWidth(), yourView.getHeight(), Bitmap.Config.ARGB_8888);
//ensure the view was added to the layout (measured) so that its width and height are greater than  zero when you create the bitmap
yourView.draw(vscr);

Example

public class CameraActivity extends ActivityCompat {


    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //...

        predictBtn.setOnClickListener(new View.OnClickListener()  {

        @Override
        public void onClick(View v) {

            img = Bitmap.createScaledBitmap(img, 128, 128, true);

            try {
                //DrawView drawView = new DrawView(getApplicationContext());
                Android model = Android.newInstance(getApplicationContext());

                // Creates inputs for reference.
                TensorImage image = TensorImage.fromBitmap(img);


                // Runs model inference and gets result.
                Android.Outputs outputs = model.process(image);
                Android.DetectionResult detectionResult = outputs.getDetectionResultList().get(0);

                // Gets result from DetectionResult.
                float score = detectionResult.getScoreAsFloat();
                RectF location = detectionResult.getLocationAsRectF();
                String category = detectionResult.getCategoryAsString();

                // Releases model resources if no longer used.
                Canvas canvas = new Canvas(img);

                drawBoundingBox(canvas, location);
                model.close();
                // here we will print out the results of the object to text views based on the image that is inputted by the user
                // we print out object type and its accuracy score
                mCanvasView.drawRect();
                objecttv.setText(category);
                scoretv.setText(Float.toString(score));

            } catch (IOException e) {
                // TODO Handle the exception
            }

        }
    });

    } //onCreate

    void drawBoundingBox(Canvas canvas, RectF location) {
        // Draw what you want
        Paint boxPaint = new Paint();
        boxPaint.setColor(Color.RED);
        boxPaint.setAlpha(200);
        boxPaint.setStyle(Paint.Style.STROKE);
        canvas.drawRect(location, boxPaint);
   }

}

Upvotes: 1

Related Questions