问题描述
我有一个摄像头预览,可以获取每个帧,对于每个帧,我都分析其中的对象,并且我有一个列表,其中包含识别出的每个对象及其位置,因此我已经有了每个对象的位置。现在我想在相机预览中围绕该对象绘制一个rect,但是做canvas.drawRect不起作用,有什么建议吗?
for (final Detector.Recognition result : results) {
final RectF location = result.getLocation();
if (location != null && result.getConfidence() >= 0.1) {
result.setLocation(location);
mappedRecognitions.add(result);
Log.d("OBJECT: ",result.getTitle());
final Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.stroke);
paint.setstrokeWidth(2.0f);
canvas_crop.drawRect(location,paint);
cropToFrameTransform.mapRect(location);
}
}
这是布局XML
<androidx.coordinatorlayout.widget.CoordinatorLayout 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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:orientation="vertical">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
<com.otaliastudios.cameraview.Cameraview
android:id="@+id/cameraview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
解决方法
如果您不需要记录矩形,那么仅在实时预览中显示这些矩形,那么通常的解决方案是覆盖专用于图形渲染的自定义视图。
创建一个自定义视图并将其放置在顶部,以确保它始终与CameraView显示的预览的位置和大小(长宽比)匹配。尽管您需要添加逻辑以确保其与CameraView “预览” 指标相匹配,但接下来的示例将使您入门。使用 setTargets 传递矩形以进行绘制:
Java:
public final class OverlayView extends View {
private final Paint paint = new Paint();
private final List<Rect> targets = new ArrayList<>();
public OverlayView(@NonNull final Context context) {
this(context,null);
}
public OverlayView(@NonNull final Context context,@Nullable final AttributeSet attrs) {
this(context,attrs,0);
}
public OverlayView(@NonNull final Context context,@Nullable final AttributeSet attrs,final int defStyleAttr) {
super(context,defStyleAttr);
final float density = context.getResources().getDisplayMetrics().density;
this.paint.setStrokeWidth(2.0f * density);
this.paint.setColor(Color.BLUE);
this.paint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
synchronized (this) {
for (final Rect entry : this.targets) {
canvas.drawRect(entry,this.paint);
}
}
}
public void setTargets(@NonNull final List<Rect> sources) {
synchronized (this) {
this.targets.clear();
this.targets.addAll(sources);
this.postInvalidate();
}
}
}
科特琳:
class OverlayView(context: Context,attrs: AttributeSet) : View(context,attrs) {
private val paint = Paint()
private val targets: MutableList<Rect> = ArrayList()
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
synchronized(this) {
for (entry in targets) {
canvas.drawRect(entry,paint)
}
}
}
fun setTargets(sources: List<Rect>) {
synchronized(this) {
targets.clear()
targets.addAll(sources)
this.postInvalidate()
}
}
init {
val density = context.resources.displayMetrics.density
paint.strokeWidth = 2.0f * density
paint.color = Color.BLUE
paint.style = Paint.Style.STROKE
}
}
对于您的特定xml,如下所示:
<androidx.coordinatorlayout.widget.CoordinatorLayout 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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:orientation="vertical">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
<com.otaliastudios.cameraview.CameraView
android:id="@+id/cameraView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<com.otaliastudios.cameraview.OverlayView
android:id="@+id/overlayView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
请注意,您对CameraView使用的是 match_parent ,应该在代码中更好地处理此问题,以适应所有可能的相机纵横比,因此,当您解析预览尺寸时,也必须应用到新的 OverlayView 。