如何在 CameraX TextureView 中绘制矩形
How to draw rectangle at CameraX TextureView
我写了下面的代码来绘制一个红色矩形,但显然它是错误的:(我没有得到任何错误,同时也没有绘制任何东西,我该如何解决它
private fun updateTransform() {
val matrix = Matrix()
// Compute the center of the view finder
val centerX = viewFinder.width / 2f
val centerY = viewFinder.height / 2f
// Correct preview output to account for display rotation
val rotationDegrees = when(viewFinder.display.rotation) {
Surface.ROTATION_0 -> 0
Surface.ROTATION_90 -> 90
Surface.ROTATION_180 -> 180
Surface.ROTATION_270 -> 270
else -> return
}
matrix.postRotate(-rotationDegrees.toFloat(), centerX, centerY)
val bmp = Bitmap.createBitmap(1425, 1425, Bitmap.Config.ARGB_8888)
val paint = Paint().apply {
isAntiAlias = true
style = Paint.Style.STROKE
color = Color.RED
strokeWidth = 10f
}
// x: {559, y: 1901}, height: 1425, width: 1425
var canvas = Canvas(bmp)
canvas.apply {
drawRect(
25.toFloat(), // faceRectangle.left,
25.toFloat(), //faceRectangle.top,
250.toFloat(),
250.toFloat(),
paint
)
}
viewFinder.unlockCanvasAndPost(canvas)
viewFinder.setTransform(matrix)
}
我找到了解决此问题的方法,不确定这是否是唯一的方法,无论如何,我会 post 在这里以防将来对某人有帮助:
- 解决方法是创建一个图像视图,与cameraX纹理视图具有相同的尺寸和位置(约束),作为覆盖,并在其上进行所有绘图,你只需要确保这个覆盖在纹理视图之上而不是在纹理视图之下,即在布局 xml 文件中跟随它。
<?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">
<TextureView
android:id="@+id/view_finder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:visibility="visible" />
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/pic_desc"
android:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
绘图代码为:
lateinit var overlay: Bitmap
private fun startCamera() {
val analyzerConfig = ImageAnalysisConfig.Builder().apply {
setImageReaderMode(
ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE)
}.build()
val analyzerUseCase = ImageAnalysis(analyzerConfig).apply {
analyzer = ImageAnalysis.Analyzer { image, rotationDegrees ->
val bitmap = view_finder.bitmap ?: return@Analyzer
overlay = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)
scope.launch(Dispatchers.Unconfined) {
val mat = Mat()
Utils.bitmapToMat(bitmap!!, mat)
val detectedFaces = FaceDetection.detectFaces(bitmap!!)
if (detectedFaces.toArray().isNotEmpty()) {
val paint = Paint().apply {
isAntiAlias = true
style = Paint.Style.STROKE
color = Color.RED
strokeWidth = 10f
}
for (rect in detectedFaces.toArray()) {
var canvas = Canvas(overlay)
canvas.drawRect(
rect.x.toFloat(),
rect.y.toFloat(),
rect.x.toFloat() + rect.width,
rect.y.toFloat() + rect.height,
paint
)
overlay?.let { Canvas(it) }?.apply {
canvas
}
}
}
}
runOnUiThread {
imageView.setImageBitmap(overlay)
}
}
}
CameraX.bindToLifecycle(this, preview, imageCapture, analyzerUseCase)
}
下面是我的应用程序的输出,现在显示了这张图:
我写了下面的代码来绘制一个红色矩形,但显然它是错误的:(我没有得到任何错误,同时也没有绘制任何东西,我该如何解决它
private fun updateTransform() {
val matrix = Matrix()
// Compute the center of the view finder
val centerX = viewFinder.width / 2f
val centerY = viewFinder.height / 2f
// Correct preview output to account for display rotation
val rotationDegrees = when(viewFinder.display.rotation) {
Surface.ROTATION_0 -> 0
Surface.ROTATION_90 -> 90
Surface.ROTATION_180 -> 180
Surface.ROTATION_270 -> 270
else -> return
}
matrix.postRotate(-rotationDegrees.toFloat(), centerX, centerY)
val bmp = Bitmap.createBitmap(1425, 1425, Bitmap.Config.ARGB_8888)
val paint = Paint().apply {
isAntiAlias = true
style = Paint.Style.STROKE
color = Color.RED
strokeWidth = 10f
}
// x: {559, y: 1901}, height: 1425, width: 1425
var canvas = Canvas(bmp)
canvas.apply {
drawRect(
25.toFloat(), // faceRectangle.left,
25.toFloat(), //faceRectangle.top,
250.toFloat(),
250.toFloat(),
paint
)
}
viewFinder.unlockCanvasAndPost(canvas)
viewFinder.setTransform(matrix)
}
我找到了解决此问题的方法,不确定这是否是唯一的方法,无论如何,我会 post 在这里以防将来对某人有帮助:
- 解决方法是创建一个图像视图,与cameraX纹理视图具有相同的尺寸和位置(约束),作为覆盖,并在其上进行所有绘图,你只需要确保这个覆盖在纹理视图之上而不是在纹理视图之下,即在布局 xml 文件中跟随它。
<?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">
<TextureView
android:id="@+id/view_finder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:visibility="visible" />
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/pic_desc"
android:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
绘图代码为:
lateinit var overlay: Bitmap
private fun startCamera() {
val analyzerConfig = ImageAnalysisConfig.Builder().apply {
setImageReaderMode(
ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE)
}.build()
val analyzerUseCase = ImageAnalysis(analyzerConfig).apply {
analyzer = ImageAnalysis.Analyzer { image, rotationDegrees ->
val bitmap = view_finder.bitmap ?: return@Analyzer
overlay = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)
scope.launch(Dispatchers.Unconfined) {
val mat = Mat()
Utils.bitmapToMat(bitmap!!, mat)
val detectedFaces = FaceDetection.detectFaces(bitmap!!)
if (detectedFaces.toArray().isNotEmpty()) {
val paint = Paint().apply {
isAntiAlias = true
style = Paint.Style.STROKE
color = Color.RED
strokeWidth = 10f
}
for (rect in detectedFaces.toArray()) {
var canvas = Canvas(overlay)
canvas.drawRect(
rect.x.toFloat(),
rect.y.toFloat(),
rect.x.toFloat() + rect.width,
rect.y.toFloat() + rect.height,
paint
)
overlay?.let { Canvas(it) }?.apply {
canvas
}
}
}
}
runOnUiThread {
imageView.setImageBitmap(overlay)
}
}
}
CameraX.bindToLifecycle(this, preview, imageCapture, analyzerUseCase)
}
下面是我的应用程序的输出,现在显示了这张图: