首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >相机预览流中的ML条形码扫描器?

相机预览流中的ML条形码扫描器?
EN

Stack Overflow用户
提问于 2018-12-19 01:42:16
回答 2查看 2.3K关注 0票数 1

我正在尝试做一个使用ML套件条形码检测器,camera2应用编程接口和Kotlin的条形码扫描仪。关于camera2我从关于ML套件条形码检测器的谷歌示例camera2basic开始,我从Scan Barcodes with ML Kit on Android开始

在Camera2BasicFragment / createCameraPreviewSession方法中,我添加了

代码语言:javascript
运行
复制
previewRequestBuilder.addTarget(imageReader!!.surface)

因此,每当有图像可用时,都会调用onImageAvailableListener。

在Camera2BasicFragment / setUpCameraOutputs方法中,我将ImageReader的ImageFormat.JPEG更改为ImageFormat YUV420_888,因此在onImageAvailableListener中,ImageReader提供YUV图像

下面是我的onImageAvailableListener:

代码语言:javascript
运行
复制
   private val onImageAvailableListener = ImageReader.OnImageAvailableListener {
        val metadata = FirebaseVisionImageMetadata.Builder()
            .setWidth(480)   // 480x360 is typically sufficient for
            .setHeight(360)  // image recognition
            .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_YV12)
            .setRotation(getRotationCompensation(cameraId, activity as Activity, context!!))
            .build()
        BarcodeReader(it.acquireNextImage(), detector, metadata, mListener).run()
    }

在元数据中,'width‘和'heigth’是ML工具包文档中建议的格式,' format‘是YV12,用于处理YUV格式

条形码阅读器是:

代码语言:javascript
运行
复制
class BarcodeReader (private val image: Image,
                     private val detector: FirebaseVisionBarcodeDetector,
                     private val metadata: FirebaseVisionImageMetadata,
                     private val mListener: IBarcodeScanner) : Runnable {
    override fun run() {
        val visionImage = FirebaseVisionImage.fromByteBuffer(image.planes[0].buffer, metadata)
        detector.detectInImage(visionImage)
            .addOnSuccessListener { barcodes ->
                // Task completed successfully
                // [START_EXCLUDE]
                // [START get_barcodes]
                for (barcode in barcodes) {
                    val bounds = barcode.boundingBox
                    val corners = barcode.cornerPoints

                    val rawValue = barcode.rawValue

                    if (rawValue!=null)
                        mListener.onBarcode(rawValue)
                }
                // [END get_barcodes]
                // [END_EXCLUDE]
            }
            .addOnFailureListener {
                // Task failed with an exception
                // ...
                Log.d("barcode", "null")
            }
        image.close()
    }

detector.detectInImage进入onSuccessListener但未检测到条形码:barcodes数组始终为空。

有人能帮帮我吗?

EN

回答 2

Stack Overflow用户

发布于 2019-02-12 04:26:58

您需要将所有三个平面的数据传递给FirebaseVisionImage.fromByteBuffer()函数。您的代码只移交第一个(Y平面)。YV12格式使用一个缓冲区(数组),其中包含Y数据,然后是U数据,然后是V数据。

图像包含三个单独的缓冲区,用于三个值(Y、U和V),但实际帧需要在一个缓冲区(数组)中包含所有这三个缓冲区。因此,您需要创建一个缓冲区,并根据格式(YV12或NV21)以正确的顺序将三个平面的内容复制到其中,然后移交该缓冲区(数组)。

请参阅this Wikipedia article和此SO问题/答案,其中包含有关YV12和NV21格式的转换和布局的更多信息。关于这些格式的另一个很好的来源是VideoLan维基。

函数可能如下所示:

代码语言:javascript
运行
复制
override fun onImageAvailable(reader: ImageReader) {
    val image = imageReader?.acquireLatestImage() ?: return
    val planes = image.planes
    if (planes.size >= 3) {
        val y = planes[0].buffer
        val u = planes[1].buffer
        val v = planes[2].buffer
        val ly = y.remaining()
        val lu = u.remaining()
        val lv = v.remaining()

        val dataYUV = ByteArray(ly + lu + lv)
        y.get(dataYUV, 0, ly)
        u.get(dataYUV, ly, lu)
        v.get(dataYUV, ly + lu, lv)

        val metadata = FirebaseVisionImageMetadata.Builder()
            .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_YV12)
            .setWidth(width)
            .setHeight(height)
            .setRotation(rotation)
            .build()

        detector.detectInImage(FirebaseVisionImage.fromByteArray(dataYUV, metadata))
    }
    image.close()
}

其中,宽度、高度和旋转取决于相机/预览和/或图像阅读器设置。

票数 0
EN

Stack Overflow用户

发布于 2020-02-04 19:29:51

使用ImageReader.OnImageAvailableListener,您可以简单地将 FirebaseVisionImage#fromMediaImage(Image image, int rotation)用于ImageFormat YUV420_888

如文档中所示:

请注意,目前我们只支持

/ YUV_420_888格式。如果您使用的是云视觉检测器,则建议使用JPEG格式;如果您使用的是设备上的检测器,则YUV_420_888会更有效。

设置ImageReader

代码语言:javascript
运行
复制
 mImageReader = ImageReader.newInstance(mVideoSize!!.width,
                mVideoSize!!.height,
                ImageFormat.YUV_420_888, 3)
        mImageReader!!.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler)

然后:

代码语言:javascript
运行
复制
private val mOnImageAvailableListener = ImageReader.OnImageAvailableListener { imageReader ->
    val image = imageReader.acquireLatestImage()
    try {
        mFaceDetector!!
                .detectInImage(
                        FirebaseVisionImage
                                .fromMediaImage(image))
                .addOnSuccessListener { firebaseVisionFaces ->
                    if (firebaseVisionFaces.size > 0) {
                        Log.d(TAG, "onSuccess: FACE DETECTED")
                    }
                }
        image.close()
    } catch (e: NullPointerException) {
        Log.e(TAG, "onImageAvailable: Invalid image provided for detection", e)
    }
}

注意:我使用了人脸检测,条形码也可以以类似的方式使用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53838413

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档