【发布时间】:2021-05-08 00:11:12
【问题描述】:
使用 CameraX 和 MLKit 检测到人脸后,我需要将图像传递给自定义 TFLite 模型(我使用的是this one),该模型会检测到面罩。该模型接受224x224像素的图像,所以我需要取出ImageProxy#getImage()对应Face#getBoundingBox()的部分并相应调整大小。
我已经看到 this answer 本来可以的,但 ThumbnailUtils.extractThumbnail() 不能使用 4 个坐标的 Rect,它相对于图像的中心,而面部的边界框可能在其他地方。
TFLite 模型接受如下输入:
val inputFeature0 = TensorBuffer
.createFixedSize(intArrayOf(1, 224, 224, 3), DataType.FLOAT32)
.loadBuffer(/* the resized image as ByteBuffer */)
请注意,ByteBuffer 的大小为 224 * 224 * 3 * 4 字节(其中 4 为 DataType.FLOAT32.byteSize())。
编辑:我已经清理了一些旧文本,因为它变得不堪重负。 code suggested below 确实有效:我只是忘了删除我自己的一段代码,它已经将相同的 ImageProxy 转换为 Bitmap 并且它一定会导致一些内部缓冲区被读取到最后,所以要么需要手动倒带或完全删除无用的代码。
但是,即使将cropRect 应用于ImageProxy 和底层Image,生成的位图仍然是完整大小的,因此必须做其他事情。该模型仍在返回 NaN 值,因此我将尝试一段时间的原始输出。
fun hasMask(imageProxy: ImageProxy, boundingBox: Rect): Boolean {
val model = MaskDetector.newInstance(context)
val inputFeature0 = TensorBuffer.createFixedSize(intArrayOf(1, 224, 224, 3), DataType.FLOAT32)
// now the cropRect is set correctly but the image itself isn't
// cropped before being converted to Bitmap
imageProxy.setCropRect(box)
imageProxy.image?.cropRect = box
val bitmap = BitmapUtils.getBitmap(imageProxy) ?: return false
val resized = Bitmap.createScaledBitmap(bitmap, 224, 224, false)
// input for the model
val buffer = ByteBuffer.allocate(224 * 224 * 3 * DataType.FLOAT32.byteSize())
resized.copyPixelsToBuffer(buffer)
// use the model and get the result as 2 Floats
val outputFeature0 = model.process(inputFeature0).outputFeature0AsTensorBuffer
val maskProbability = outputFeature0.floatArray[0]
val noMaskProbability = outputFeature0.floatArray[1]
model.close()
return maskProbability > noMaskProbability
}
【问题讨论】:
-
您好,您可以查看我在这里提供的解决方案stackoverflow.com/a/67348548/13300615。它应该可以帮助您在不将其转换为位图的情况下获得裁剪的图像。
标签: android kotlin tensorflow-lite android-camerax google-mlkit