在相机预览上绘制矩形。

huangapple go评论97阅读模式
英文:

Draw rect over camera preview

问题

我有一个相机预览,我获取每一帧图像,对于每一帧图像,我分析其中的物体,并且我有一个包含每个被识别物体及其位置的列表,因此我已经获取了每个单独物体的位置。现在我想在相机预览上绘制一个围绕着该物体的矩形,但使用 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>

(注意:我已经移除了你提供的原始文本,并只返回了翻译好的部分,如你所要求。)

英文:

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?

                for (final Detector.Recognition result : results) {
                final RectF location = result.getLocation();
                if (location != null &amp;&amp; result.getConfidence() &gt;= 0.1) {
                    result.setLocation(location);
                    mappedRecognitions.add(result);
                    Log.d(&quot;OBJECT: &quot;, 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

&lt;androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
xmlns:tools=&quot;http://schemas.android.com/tools&quot;
android:layout_width=&quot;match_parent&quot;
android:layout_height=&quot;match_parent&quot;
tools:context=&quot;.MainActivity&quot;&gt;

&lt;RelativeLayout
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    android:background=&quot;@android:color/black&quot;
    android:orientation=&quot;vertical&quot;&gt;


    &lt;FrameLayout
        android:id=&quot;@+id/container&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot;&gt;

    &lt;/FrameLayout&gt;

    &lt;com.otaliastudios.cameraview.CameraView
        android:id=&quot;@+id/cameraView&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot;/&gt;
&lt;/RelativeLayout&gt;


&lt;/androidx.coordinatorlayout.widget.CoordinatorLayout&gt;

答案1

得分: 2

如果您不需要记录矩形,只需要在实时预览中显示矩形,那么通常的解决方案是叠加一个专门用于绘制图形的自定义视图。

创建一个自定义视图并将其放置在顶部,确保它始终与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) {
        // ...(构造函数代码)
    }

    // ...(其他构造函数)

    @Override
    protected void onDraw(final Canvas canvas) {
        // ...(onDraw方法代码)
    }

    public void setTargets(@NonNull final List<Rect> sources) {
        // ...(setTargets方法代码)
    }
}

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) {
        // ...(onDraw方法代码)
    }

    fun setTargets(sources: List<Rect>) {
        // ...(setTargets方法代码)
    }

    init {
        // ...(初始化块代码)
    }
}

至于您的特定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

英文:

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. Next an example to get you started, although you will need to add the logic to ensure it matches the CameraView "preview" metrics. Use the setTargets to pass the rectangles to paint:

Java:

public final class OverlayView extends View {
    private final Paint paint = new Paint();
    private final List&lt;Rect&gt; targets = new ArrayList&lt;&gt;();

    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&lt;Rect&gt; 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&lt;Rect&gt; = ArrayList()

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        synchronized(this) {
            for (entry in targets) {
                canvas.drawRect(entry, paint)
            }
        }
    }

    fun setTargets(sources: List&lt;Rect&gt;) {
        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:

&lt;androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
xmlns:tools=&quot;http://schemas.android.com/tools&quot;
android:layout_width=&quot;match_parent&quot;
android:layout_height=&quot;match_parent&quot;
tools:context=&quot;.MainActivity&quot;&gt;

&lt;RelativeLayout
	android:layout_width=&quot;match_parent&quot;
	android:layout_height=&quot;match_parent&quot;
	android:background=&quot;@android:color/black&quot;
	android:orientation=&quot;vertical&quot;&gt;


	&lt;FrameLayout
		android:id=&quot;@+id/container&quot;
		android:layout_width=&quot;match_parent&quot;
		android:layout_height=&quot;match_parent&quot;&gt;

	&lt;/FrameLayout&gt;

	&lt;com.otaliastudios.cameraview.CameraView
		android:id=&quot;@+id/cameraView&quot;
		android:layout_width=&quot;match_parent&quot;
		android:layout_height=&quot;match_parent&quot;/&gt;
		
	&lt;com.otaliastudios.cameraview.OverlayView 
		android:id=&quot;@+id/overlayView&quot;
		android:layout_width=&quot;match_parent&quot;
		android:layout_height=&quot;match_parent&quot;/&gt;
		
&lt;/RelativeLayout&gt;


&lt;/androidx.coordinatorlayout.widget.CoordinatorLayout&gt;

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.

huangapple
  • 本文由 发表于 2020年10月23日 22:28:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/64501915.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定