android ML试剂盒条形码扫描未检测到监视器屏幕照片中的QR代码

j2cgzkjk  于 2023-01-28  发布在  Android
关注(0)|答案(1)|浏览(203)

我正在使用com.google.mlkit:barcode-scanning:17.0.2检测图片中的QR码。
从图库中获取URI后,我创建InputImage,然后使用BarcodeScanner处理此图像以查找QR码。当我选择纸上QR码的照片时,找到了QR码。但当我拍摄监视器屏幕上QR码的照片时,却从未找到QR码。我应该做些什么才能在监视器屏幕的照片中检测到QR码?

  • (当我使用与CameraX相同的扫描仪进行实时QR码检测时,它在监视器屏幕上找到代码)*
val image = InputImage.fromFilePath(context, uri)

val scanOptions =
    BarcodeScannerOptions.Builder()
        .setBarcodeFormats(
            Barcode.FORMAT_QR_CODE,
        )
        .build()

val scanner = BarcodeScanning.getClient(scanOptions)

scanner.process(image)
    .addOnSuccessListener {
        val code = it.getOrNull(0)?.rawValue
        if (code == null) {
            // code NOT found
        } else {
            // code was found
        }
    }

在纸上找到的QR码示例

未找到监视器屏幕上的QR代码示例

ux6nzvsh

ux6nzvsh1#

您很可能正在与Moiré effect对抗。根据QR检测算法的不同,Moiré效应引入的高频可能会使检测器偏离轨道。令人沮丧的是,通常是"更好"的QR码检测器被Moiré图案击败。
较好的解决方法是:

  • 以最高的分辨率拍摄照片
  • 使图像模糊
  • 如果可能,将对比度增加到最大值
  • (可选地)运行sigma阈值处理,或者仅仅将亮度分量低于32的所有像素重写为0,将亮度分量高于224的所有像素重写为255。

执行大致相同操作的另一种方法是

  • 以最高的分辨率拍摄照片
  • 如果可能,将对比度增加到最大值
  • 将图像降采样到分辨率低得多

第二种方法的结果较差,但通常可以使用设备原语实现。
显示器的另一个问题来源(据我所见不在你的图片中)是刷新率,有时候,您会发现,二维码实际上是图片上半部分曝光过度的二维码,图片下半部分曝光不足的二维码,两者都无法识别,这种影响是由于显示器的刷新率和刷新策略造成的,不容易解决-您可以尝试降低显示器的亮度以增加曝光时间,直到超过1/50或1/25秒,或者从更远的地方拍摄照片并使用数字变焦。现代显示器具有更高的刷新率,实际上刷新时间超过其自身的停留时间,因此不应该发生这种情况;然而,使用旧的模拟显示器,每次都会发生这种情况。
∮第三种疯狂的方式∮
这是偶然发现的,但即使在廉价的硬件上也能很好地工作,只要QR SDK或库提供一些小的额外装饰。
1.以您能获得的最高帧速率(25 fps?)拍摄长度约为1秒的视频
1.从中间(例如,第13帧),提取三个QR "路点"-SDK中可能有一个名为"containsQRCode"的低级函数()"执行此操作。如果它返回 * true *,找到航点并返回其坐标,以便执行定标/估计。它可能返回置信度图("此图片 * 似乎 * 包含概率为X %的QR码")。这些是应用程序用来在候选QR码周围显示边框或红点的API。如果您的SDK没有这些API,抱歉......您的运气不好。
1.获取之前和之后的帧(第12和14帧),然后是第11和15帧,依此类推。如果其中任何帧返回有效的QR码,则您可以高枕无忧。
1.如果在足够多的帧中找到QR码(即使没有正确解码),但航点坐标变化很大,则手不稳定-告诉用户。
1.如果你有足够多的坐标变化很小的帧,你可以在这些帧上居中和对齐,并平均帧。然后在生成的图像上运行真正的QRCode识别。这可以100%消除莫尔效应,并大幅减少显示器驻留噪声,几乎没有信息损失。结果比分辨率变化要好得多。这在分辨率改变时重置相机的(一些)设备上不容易执行。
这在一个19美元的ESP32物联网设备上工作,该设备在嘈杂、振动丰富的环境中运行(它从移动运输带上的纸箱的相机图像中获取QR代码)。

相关问题