用增强现实和DynamSoft条形码读取器标记多个条形码
#android #ar #barcode #arcore

术语“ 增强现实(AR)通常是指实时将数字信息与用户环境集成。 AR可以使用户界面更加沉浸式和直观,将实时信息叠加到现实世界中,以使任务更加高效且容易发生错误。例如,在仓库管理中,AR可用于跟踪货架上物品的清单。在医院,AR可以帮助识别管和瓶子,在零售中,它可以显示产品信息。在本文中,我们将演示如何使用ARCoreDynamsoft Barcode Reader标记多个条形码并避免误读。

先决条件

2D条形码覆盖摄像机预览

通常,我们在相机预览上显示条形码结果如下:

barcode 2D overlay

覆盖层呈现在位于相机预览上方的2D画布上,同时显示条形码信息及其边界框。

在相机视图上绘制覆盖层可以被视为增强现实的基本形式。一个更先进的AR系统通常涉及了解环境的几何形状并以使它们在现实世界中似乎存在的方式放置数字对象,从而适当响应相机的视图或环境本身的变化。

在以下各节中,我们将结合Arcore和DynamSoft条形码读取器SDK,以增强条形码扫描体验。

关于Arcore和DynamSoft条形码读取器

  • Arcore是Google建立增强现实(AR)体验的平台。通过利用三个关键技术 - 运动跟踪,环境理解和光估计 - 弧形使您的手机能够感知其环境,了解世界并以更全面和上下文的方式与信息互动。
  • DynamSoft条形码读取器SDK是用于Windows,Linux,MacOS,Android,iOS和Web的商业条形码扫描库。它支持各种条形码类型,包括QR代码,Datamatrix,PDF417,代码128,代码39,EAN 13,UPC-A等。它还提供了30天的免费试用许可证。

将Google的Arcore与Dynamoft Android条形码SDK结合在一起

让我们从Arcore的示例项目开始:https://github.com/googlesamples/arcore-ml-sample

Kotlin中编写的Android样品演示了如何利用Arcore和计算机视觉算法进行对象检测和跟踪。对我们来说,主要目标是对条形码的检测和跟踪。将DynamSoft条形码读取器集成到示例项目中涉及一系列步骤。

将DynamSoft条形码读取器SDK添加到项目

  1. 将DynamSoft存储库来源https://download2.dynamsoft.com/maven/aar添加到项目的build.gradle文件:

    allprojects {
        repositories {
            google()
            mavenLocal()
            mavenCentral()
            maven {
                url "https://download2.dynamsoft.com/maven/aar"
            }
        }
    }
    
  2. 在应用程序的build.gradle文件中配置依赖关系:

    implementation 'com.dynamsoft:dynamsoftbarcodereader:9.6.20'
    

在Kotlin中检测条形码,QR码和datamatrix

  1. MainActivity.kt中,设置许可证密钥。您可以从here获得免费的试用许可证。

    import com.dynamsoft.dbr.BarcodeReader
    
    BarcodeReader.initLicense("LICENSE-KEY") { isSuccessful, e ->
      runOnUiThread {
        if (!isSuccessful) {
          e.printStackTrace()
          Log.e(TAG, "Failed to verify the license: $e")
        }
      }
    }
    
  2. AppRenderer.kt中创建条形码读取器对象:

    import com.dynamsoft.dbr.BarcodeReader
    import com.dynamsoft.dbr.BarcodeReaderException
    import com.dynamsoft.dbr.EnumImagePixelFormat
    import com.dynamsoft.dbr.Point
    
    var reader: BarcodeReader? = null
    
    fun bindView(view: MainActivityView) {
        try {
          reader = BarcodeReader()
          val settings = reader!!.runtimeSettings
          settings.expectedBarcodesCount = 999
          reader!!.updateRuntimeSettings(settings)
        } catch (e: BarcodeReaderException) {
          e.printStackTrace()
        }
    }
    
  3. 找到以launch(Dispatchers.IO)开头的代码块。您可以利用获得的相机图像检测条形码:

    if (reader != null) {
        var bytes = ByteArray(cameraImage.planes[0].buffer.remaining())
        cameraImage.planes[0].buffer.get(bytes)
    
        var results = reader!!.decodeBuffer(bytes, cameraImage.width, cameraImage.height, cameraImage.planes[0].rowStride, EnumImagePixelFormat.IPF_NV21)
        objectResults = emptyList()
        if (results != null && results.isNotEmpty()) {
        val tmp: MutableList<DetectedObjectResult> = mutableListOf()
        for (result in results) {
            var points = result.localizationResult.resultPoints
            var confidence = 100
    
            val (x1, y1) = points[0].x to points[0].y
            val (x2, y2) = points[1].x to points[1].y
            val (x3, y3) = points[2].x to points[2].y
            val (x4, y4) = points[3].x to points[3].y
            val centerX = (x1 + x2 + x3 + x4) / 4
            val centerY = (y1 + y2 + y3 + y4) / 4
            val content = result.barcodeText
            val label = "✓"
    
            val detectedObjectResult = DetectedObjectResult(confidence.toFloat(), label, centerX.toInt() to centerY.toInt(), content)
            tmp.add(detectedObjectResult)
        }
        objectResults = tmp
        }
    }
    

条形码检测结果包含四个点,这是条形码的四个角。我们可以计算条形码的中心点并将其用作标签的锚点。

val (x1, y1) = points[0].x to points[0].y
val (x2, y2) = points[1].x to points[1].y
val (x3, y3) = points[2].x to points[2].y
val (x4, y4) = points[3].x to points[3].y
val centerX = (x1 + x2 + x3 + x4) / 4
val centerY = (y1 + y2 + y3 + y4) / 4

我们将条形码结果转换为DetectedObjectResult列表,稍后将在屏幕上渲染。

如果将label设置为result.barcodeText,则条形码的内容将显示在屏幕上。

barcode content

该效果适用于孤立的条形码。但是,如果相机视图中出现多个条形码,则显示器可能会过度拥挤。要解决此问题,我们可以将label设置为并在列表视图中显示条形码内容。

barcode detection results

启用相机自动焦点

默认情况下,ARCORE摄像机设置为固定焦点,这可以使条形码显得模糊。为了提高条形码检测准确性,必须使用自动焦点。

将开关按钮添加到UI中以切换焦点模式。

  1. activity_main.xml布局文件中创建一个开关按钮:

    <androidx.appcompat.widget.SwitchCompat
          android:id="@+id/switch_focus_mode"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_alignParentEnd="true"
          android:checked="false"
          android:text="@string/switch_focus_mode"
          android:textColor="#ffffff" />
    
  2. MainActivityView.kt中,获取对开关按钮的引用:

    var focusModeSwitch = root.findViewById<SwitchCompat>(R.id.switch_focus_mode)
    
  3. AppRenderer.kt中注册开关按钮的OnCheckedChangeListener

    view.focusModeSwitch.setOnCheckedChangeListener { _, isChecked ->
      val session = activity.arCoreSessionHelper.sessionCache ?: return@setOnCheckedChangeListener
      val config = session.config
      config.focusMode = if (isChecked) Config.FocusMode.AUTO else Config.FocusMode.FIXED
      session.configure(config)
    }
    

源代码

https://github.com/yushulx/android-arcore-barcode-qr-detection