Can anybody show me how to draw a rectangle over cameraX preview? I tried implementing a custom view as suggested by past stack overflow answers that were written in kotlin but it does not seemed to be working for me when I attempted to convert it into Java.
XML File
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity"
android:id="@+id/my_root">
<com.example.cameraxxx.RectOverlay
android:id="@+id/rectOverlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.camera.view.PreviewView
android:id="@+id/previewView"
android:layout_width="0dp"
android:layout_height="0dp"
android:contentDescription="preview_area"
android:importantForAccessibility="no"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0">
</androidx.camera.view.PreviewView>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="13dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="@+id/previewView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity Extract
imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
@SuppressLint("UnsafeExperimentalUsageError")
@Override
public void analyze(@NonNull ImageProxy imageProxy) {
int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees();
FaceDetectorOptions realTimeOpts =
new FaceDetectorOptions.Builder()
.setPerformanceMode(1).enableTracking()
.build();
Image mediaImage = imageProxy.getImage();
if(mediaImage != null) {
InputImage image = InputImage.fromMediaImage(mediaImage,imageProxy.getImageInfo().getRotationDegrees());
FaceDetector detector = FaceDetection.getClient(realTimeOpts);
Task<List<Face>> result =
detector.process(image)
.addOnSuccessListener(
new OnSuccessListener<List<Face>>() {
@Override
public void onSuccess(List<Face> faces) {
// Task completed successfully
// ...
if(faces.size() !=0){
rectOverlay.setAlpha(1f);
Toast.makeText(MainActivity.this,"Face detected",Toast.LENGTH_SHORT).show();
Canvas canvas = new Canvas();
for (Face face: faces){
rectOverlay.drawOverlay(face,canvas);
}
}
}
})
.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// Task failed with an exception
// ...
Log.d("y123","nno face");
}
})
.addOnCompleteListener(
new OnCompleteListener<List<Face>>() {
@Override
public void onComplete(@NonNull Task<List<Face>> task) {
imageProxy.close();
}
});
}
}
});
cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, imageAnalysis, preview);
preview.setSurfaceProvider(mPreviewView.createSurfaceProvider());
}
RectOverlay Class
package com.example.cameraxxx;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import com.google.mlkit.vision.face.Face;
public class RectOverlay extends View {
private Paint paint;
public RectOverlay(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.FILL);
}
public void drawOverlay(Face face, Canvas canvas){
canvas.drawRect(face.getBoundingBox().left,face.getBoundingBox().top, face.getBoundingBox().right, face.getBoundingBox().bottom, paint);
invalidate();
}
}