Android 如何裁剪和调整矩形边界框内图像部分的大小?
在使用CameraX和MLKit检测到人脸后,我需要将图像传递到一个自定义TFLite模型(我正在使用),该模型检测到一个面罩。该模型接受224x224像素的图像,因此我需要取出Android 如何裁剪和调整矩形边界框内图像部分的大小?,android,kotlin,tensorflow-lite,android-camerax,google-mlkit,Android,Kotlin,Tensorflow Lite,Android Camerax,Google Mlkit,在使用CameraX和MLKit检测到人脸后,我需要将图像传递到一个自定义TFLite模型(我正在使用),该模型检测到一个面罩。该模型接受224x224像素的图像,因此我需要取出ImageProxy#getImage()对应于Face#getBoundingBox()的部分,并相应地调整其大小 我已经看到了可以使用的选项,但是ThumbnailUtils.extractThumbnailUtils()无法使用4个坐标的Rect,并且它相对于图像的中心,而人脸的边界框可能在其他位置 TFLite模
ImageProxy#getImage()
对应于Face#getBoundingBox()
的部分,并相应地调整其大小
我已经看到了可以使用的选项,但是ThumbnailUtils.extractThumbnailUtils()
无法使用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()
)
编辑:我已经清理了一些旧文本,因为它变得越来越难以理解。实际上是这样的:我只是忘记了删除我自己的一段代码,它已经将相同的
ImageProxy
转换为Bitmap
,它一定导致一些内部缓冲区一直被读取到最后,所以要么需要手动倒带,要么完全删除无用的代码
但是,即使将cropRect
应用于ImageProxy
和底层的图像
,生成的位图仍然是全尺寸的,因此必须执行其他操作。模型仍然返回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
}
在使用ML工具包时,我们将提供更好的方法来处理图像处理 目前,您可以尝试以下方法:
它会将ImageProxy转换为位图,并将其旋转为直立。人脸检测的边界框应直接应用于位图,这意味着您应该能够使用矩形边界框裁剪位图。谢谢,我等不及CameraX未来的改进了。通过说“边界框应直接应用于位图”,您的意思是在使用
InputImage.fromBitmap()
调用detector.process()
后,我必须执行imageProxy.cropRect=boundingBox
并将imageProxy
再次转换为位图?我肯定我没有得到什么东西,因为它看起来有点复杂。在修复了一些东西之后,你建议的代码终于工作了,但是图像仍然没有被裁剪。我已经用最近的更改更新了问题。imageProxy.setCropRect(box)
不会为您裁剪图像。调整图像大小后,可以使用此方法裁剪带有检测到的边界框的图像。是的,我已经发现最好(可能也是唯一)的方法是从另一个分区创建一个新位图,如val cropped=bitmap.createBitmap(bitmap,boundingbox.left,boundingbox.top,boundingbox.width(),boundingBox.height())
。您好,您可以看看我在这里给出的解决方案。它应该可以帮助您获得裁剪图像,而无需将其转换为位图。