android - 使用 CameraX 分析时如何选择图像的一部分
问题描述
我正在使用 CameraX,然后使用 FirebaseVision 从图像中读取一些文本。当我分析图像时,我想选择图像的一部分,而不是整个图像,就像您使用条形码扫描仪时一样。
class Analyzer : ImageAnalysis.Analyzer {
override fun analyze(imageProxy: ImageProxy?, rotationDegrees: Int) {
// how to crop the image in here?
val image = imageProxy.image
val imageRotation = degreesToFirebaseRotation(degrees)
if (image != null) {
val visionImage = FirebaseVisionImage.fromMediaImage(image, imageRotation)
val textRecognizer = FirebaseVision.getInstance().onDeviceTextRecognizer
textRecognizer.processImage(visionImage)
}
}
我想知道,有没有办法裁剪图像?
解决方案
你的问题正是我两个月前解决的问题......
object YuvNV21Util {
fun yuv420toNV21(image: Image): ByteArray {
val crop = image.cropRect
val format = image.format
val width = crop.width()
val height = crop.height()
val planes = image.planes
val data =
ByteArray(width * height * ImageFormat.getBitsPerPixel(format) / 8)
val rowData = ByteArray(planes[0].rowStride)
var channelOffset = 0
var outputStride = 1
for (i in planes.indices) {
when (i) {
0 -> {
channelOffset = 0
outputStride = 1
}
1 -> {
channelOffset = width * height + 1
outputStride = 2
}
2 -> {
channelOffset = width * height
outputStride = 2
}
}
val buffer = planes[i].buffer
val rowStride = planes[i].rowStride
val pixelStride = planes[i].pixelStride
val shift = if (i == 0) 0 else 1
val w = width shr shift
val h = height shr shift
buffer.position(rowStride * (crop.top shr shift) + pixelStride * (crop.left shr shift))
for (row in 0 until h) {
var length: Int
if (pixelStride == 1 && outputStride == 1) {
length = w
buffer[data, channelOffset, length]
channelOffset += length
} else {
length = (w - 1) * pixelStride + 1
buffer[rowData, 0, length]
for (col in 0 until w) {
data[channelOffset] = rowData[col * pixelStride]
channelOffset += outputStride
}
}
if (row < h - 1) {
buffer.position(buffer.position() + rowStride - length)
}
}
}
return data
}
}
然后将字节数组转换为位图
object BitmapUtil {
fun getBitmap(data: ByteArray, metadata: FrameMetadata): Bitmap {
val image = YuvImage(
data, ImageFormat.NV21, metadata.width, metadata.height, null
)
val stream = ByteArrayOutputStream()
image.compressToJpeg(
Rect(0, 0, metadata.width, metadata.height),
80,
stream
)
val bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size())
stream.close()
return rotateBitmap(bmp, metadata.rotation, false, false)
}
private fun rotateBitmap(
bitmap: Bitmap, rotationDegrees: Int, flipX: Boolean, flipY: Boolean
): Bitmap {
val matrix = Matrix()
// Rotate the image back to straight.
matrix.postRotate(rotationDegrees.toFloat())
// Mirror the image along the X or Y axis.
matrix.postScale(if (flipX) -1.0f else 1.0f, if (flipY) -1.0f else 1.0f)
val rotatedBitmap =
Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
// Recycle the old bitmap if it has changed.
if (rotatedBitmap != bitmap) {
bitmap.recycle()
}
return rotatedBitmap
}
}
请查看我的开源项目https://github.com/minkiapps/Firebase-ML-Kit-Scanner-Demo,我构建了一个演示应用程序,其中图像代理的一部分在由 ml kit 处理之前被裁剪。
推荐阅读
- ssl - 在具有 TLS 的服务器中仅启用 secp384r1 时,0-RTT 不起作用。为什么?
- vue.js - 尝试不显示 v-model 更改,直到我想显示它
- excel - 如何从excel中两个日期之间的日期列表中省略周末日期
- c++ - 将 2 个 32 位整数相乘而不会溢出
- java - 无法为 Android 应用程序初始化应用程序检查
- amazon-web-services - AWS Lambda/Secrets Manager 权限不再起作用 (Pulumi)
- swift - 我正在尝试从 Swift 5 输入格式化的日期字符串为“yyyy-mm-dd H:i:s +0000”mySQL。相反,我得到“yyyy-mm-dd H:i:s 0000”。如何添加“+”?
- tensorflow - 如何正确测试张量流模型的运行时间
- python - 如果来自 Python 字典的子类,则 LRU 缓存不可散列的类型
- python - 如何根据python中特定列中的值将数据集划分为多个数据集?