为啥 FirebaseVisionImage.fromMediaImage() 会产生 OutOfMemoryError
Posted
技术标签:
【中文标题】为啥 FirebaseVisionImage.fromMediaImage() 会产生 OutOfMemoryError【英文标题】:Why FirebaseVisionImage.fromMediaImage() produces OutOfMemoryError为什么 FirebaseVisionImage.fromMediaImage() 会产生 OutOfMemoryError 【发布时间】:2020-08-05 09:29:33 【问题描述】:构建CameraX,调用analyze()方法并传递图像,然后使用close()方法关闭(删除)。从此图像创建并传递 FirebaseVisionImage 以进行处理(文本识别)。代码示例和代码实验室不同,不使用 CameraX 或旧 API 版本实现 TextRecognition。
override fun analyze(imageProxy: ImageProxy)
if (isValidText)
imageProxy.close()
return
val mediaImage = imageProxy.image // requires annotation
val degrees = imageProxy.imageInfo.rotationDegrees
val rotation = rotationDegreesToFirebaseRotation(degrees)
if (mediaImage != null)
runTextRecognition(mediaImage, rotation) // line 44
imageProxy.close()
private fun runTextRecognition(mediaImage: Image, rotation: Int)
// Create FirebaseVisionImage from frame
val visionImage = FirebaseVisionImage.fromMediaImage(mediaImage, rotation) // line 64
val recognizer = FirebaseVision.getInstance()
.onDeviceTextRecognizer
recognizer.processImage(visionImage)
.addOnSuccessListener texts ->
processTextRecognitionResult(texts!!, recognizer)
if (isValidText)
recognizer.close()
return@addOnSuccessListener
.addOnFailureListener e -> // Task failed with an exception
e.printStackTrace()
在我的项目中,我正在使用这个依赖项
def firebase_version = '24.0.2'
def camerax_version = '1.0.0-beta02'
implementation "com.google.firebase:firebase-ml-vision:$firebase_version"
implementation "androidx.camera:camera-camera2:$camerax_version"
implementation "androidx.camera:camera-view:1.0.0-alpha09"
implementation "androidx.camera:camera-lifecycle:$camerax_version"
这就是我构建 CameraX 的方式
private fun bindPreview(cameraProvider: ProcessCameraProvider)
// Get screen metrics used to setup camera for full screen resolution
val metrics = DisplayMetrics().also viewFinder?.display?.getRealMetrics(it)
val screenAspectRatio = aspectRatio(metrics.widthPixels, metrics.heightPixels)
val rotation = viewFinder?.display?.rotation
// Set up the preview use case to display camera preview
val preview = Preview.Builder()// Request aspect ratio but no resolution
.setTargetAspectRatio(screenAspectRatio)
// Set initial target rotation
.setTargetRotation(rotation!!)
.build()
// Choose the camera by requiring a lens facing
val cameraSelector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build()
val executor = Executors.newSingleThreadExecutor()
// Must unbind the use-cases before rebinding them
cameraProvider.unbindAll()
val imageAnalyzer = ImageAnalysis.Builder()
// Request aspect ratio but no resolution
.setTargetAspectRatio(screenAspectRatio)
// Set initial target rotation, have to call this again if rotation changes
// during the lifecycle of this use case
.setTargetRotation(rotation)
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
imageAnalyzer.setAnalyzer(executor, analyzer)
var camera = cameraProvider.bindToLifecycle(viewFinder?.context as LifecycleOwner, cameraSelector, preview, imageAnalyzer)
// Attach the viewfinder's surface provider to preview use case
preview.setSurfaceProvider(viewFinder?.createSurfaceProvider(camera.cameraInfo))
【问题讨论】:
【参考方案1】:我能够通过切换到 mlkit 来解决问题。
首先更新 app/build.gradle 文件以使用 mlkit 而不是 firebase:
// Add ML Kit dependencies
implementation 'com.google.android.gms:play-services-mlkit-text-recognition:16.1.0'
接下来更新分析器以使用 InputImage:
@androidx.camera.core.ExperimentalGetImage
private class TextAnalyzer(private val listener: TextListener) : ImageAnalysis.Analyzer
override fun analyze(imageProxy: ImageProxy)
val mediaImage: Image = imageProxy.image ?: return
val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
runTextRecognition(image)
imageProxy.close()
然后将runTextRecognition
更新为:
private fun runTextRecognition(image: InputImage)
val recognizer = TextRecognition.getClient()
recognizer.process(image)
...
应该可以的。
Here 是提供更多细节的代码实验室。
【讨论】:
以上是关于为啥 FirebaseVisionImage.fromMediaImage() 会产生 OutOfMemoryError的主要内容,如果未能解决你的问题,请参考以下文章
为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?