Reputation: 351
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
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