简体   繁体   English

在相机预览上绘制矩形

[英]Draw rect over camera preview

I have a camera preview where i get every frame, for each frame i analyze the objects inside and i have a list that contain every object recognized and the location, so i have already the locations for every single object.我有一个相机预览,我可以在其中获取每一帧,对于每一帧,我都会分析里面的对象,并且我有一个包含识别出的每个对象和位置的列表,所以我已经有了每个对象的位置。 Now i want to draw a rect around that object on camera preview, but doing canvas.drawRect doesn't work, any suggestion?现在我想在相机预览上围绕该对象绘制一个矩形,但是做 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);
                }
            }

This is the layout XML这是布局 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>

If you don't need the rectangles to be recorded, so, are only displayed in the live preview, then in general the solution is to overlay a custom view dedicated exclusively to rendering of drawings.如果您不需要记录矩形,因此只在实时预览中显示,那么通常的解决方案是覆盖一个专门用于渲染图纸的自定义视图。

Create a custom view and place it on top, ensuring it always matches the position and size (aspect ratio) of the preview shown by the CameraView.创建自定义视图并将其放在顶部,确保它始终CameraView 显示的预览的位置和大小(纵横比)相匹配 Next an example to get you started, although you will need to add the logic to ensure it matches the CameraView "preview" metrics.接下来是一个让您入门的示例,尽管您需要添加逻辑以确保它与 CameraView “预览”指标相匹配。 Use the setTargets to pass the rectangles to paint:使用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, attrs, 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();
        }
    }
}

Kotlin:科特林:

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
    }
}

And for your specific xml, would be as next:对于您的特定 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>

Note that you are using match_parent for the CameraView, this should be handled better in code to adjust into all possible camera aspect ratios, and consequently when you resolve the preview size, such must be also applied to the new OverlayView .请注意,您正在为 CameraView 使用match_parent ,这应该在代码中更好地处理以调整到所有可能的相机纵横比,因此当您解析预览大小时,这也必须应用于新的OverlayView

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM