英文:
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 && 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
<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>
答案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<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:
<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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论