【问题标题】:Unity Zxing QR code scanner integrationUnity Zxing 二维码扫描仪集成
【发布时间】:2015-05-30 13:03:49
【问题描述】:

我需要将 Zxing 与 vuforia 集成以在 Unity 中制作二维码扫描应用程序吗? 我不知道如何将 Zxing 与 Vuforia 统一集成。有人可以指导我如何做到这一点吗?我有 Zxing .dll 文件和 Vuforia 统一包。提前致谢。

【问题讨论】:

    标签: unity3d zxing qr-code barcode-scanner vuforia


    【解决方案1】:

    我今天正在寻找在 Unity 中将 Zxing 与 vuforia 集成。

    首先要做的是从https://zxingnet.codeplex.com/ 下载 dll 并将统一 dll 复制到您的 Plugins 文件夹(应该在 Assets 文件夹中)

    然后,我设法找到了一些例子(有些论文已经过时了):

    合并这些示例并简化它们后,我得到了这样的东西(放置在 ARCamera 预制件中):

    using UnityEngine;
    using System;
    using System.Collections;
    
    using Vuforia;
    
    using System.Threading;
    
    using ZXing;
    using ZXing.QrCode;
    using ZXing.Common;
    
    
    [AddComponentMenu("System/VuforiaScanner")]
    public class VuforiaScanner : MonoBehaviour
    {    
        private bool cameraInitialized;
    
        private BarcodeReader barCodeReader;
    
        void Start()
        {        
            barCodeReader = new BarcodeReader();
            StartCoroutine(InitializeCamera());
        }
    
        private IEnumerator InitializeCamera()
        {
            // Waiting a little seem to avoid the Vuforia's crashes.
            yield return new WaitForSeconds(1.25f);
    
            var isFrameFormatSet = CameraDevice.Instance.SetFrameFormat(Image.PIXEL_FORMAT.RGB888, true);
            Debug.Log(String.Format("FormatSet : {0}", isFrameFormatSet));
    
            // Force autofocus.
            var isAutoFocus = CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
            if (!isAutoFocus)
            {
                CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
            }
            Debug.Log(String.Format("AutoFocus : {0}", isAutoFocus));
            cameraInitialized = true;
        }
    
        private void Update()
        {
            if (cameraInitialized)
            {
                try
                {
                    var cameraFeed = CameraDevice.Instance.GetCameraImage(Image.PIXEL_FORMAT.RGB888);
                    if (cameraFeed == null)
                    {
                        return;
                    }
                    var data = barCodeReader.Decode(cameraFeed.Pixels, cameraFeed.BufferWidth, cameraFeed.BufferHeight, RGBLuminanceSource.BitmapFormat.RGB24);
                    if (data != null)
                    {
                        // QRCode detected.
                        Debug.Log(data.Text);
                    }
                    else
                    {
                        Debug.Log("No QR code detected !");
                    }
                }
                catch (Exception e)
                {
                    Debug.LogError(e.Message);
                }
            }
        }    
    }
    

    我设法让它在 AVD(Android 虚拟设备)中运行,因此它可以在真实设备上运行。

    【讨论】:

    • 嘿兄弟...什么都没有发生,只是一个黑屏出现在 android 设备中。我认为相机没有初始化。
    • Vuforia 为您的设备采用默认网络摄像头。您是否将“AR 相机”拖放到您的场景中?如果您有网络摄像头,则可以直接在 Unity 中测试所有 Vuforia 功能
    • 修复了黑屏的问题。iFrameFormatSet的值现在也为真了。但是二维码没有解码。总是它的值是空的。它打印“没有检测到二维码!”
    • 我用一个功能性的代码来编辑我的代码。我将像素格式更改为 RGB888 并使用 BarcodeReader 而不是 QRCodeReader。我设法让这段代码在虚拟设备上运行。
    • 感谢您的帮助!顺便说一句,我的智能手机有点滞后,有没有办法让它更流畅?也许我错过了一些冒名顶替?
    【解决方案2】:

    如果您使用 Unity 5.x 和 64 位 Windows,您可能会遇到错误

    加载资产/插件/QCARWrapper.dll 失败

    解决方法很简单,如问题Unity3d - Failed to load 'Assets/Plugins/QCARWrapper.dll'中所述

    1. 要将 Vuforia 与 Unity 64 位一起使用,只需将 QCARWrapper DLL 从 /Plugins 移动到 /Plugins/x86. 这些是 DLL:

    2. 在 Unity Project 视图中选择 QCARWrapper.bundle(位于 Assets > Plugins 下),以便其设置显示在 Unity Inspector 中将 Unity 检查器中 QCARWrapper.bundle 的设置从 Any Platform 更改为 Standalone + 编辑器。

    它就像一个魅力。

    【讨论】:

      【解决方案3】:

      如果您在扫描过程中遇到延迟,此代码应该可以帮助您。我使用了KDelli的答案,并使用了另一个线程来解码qr的代码。

      using UnityEngine;
      using System;
      using System.Collections;
      
      using Vuforia;
      
      using System.Threading;
      
      using ZXing;
      using ZXing.QrCode;
      using ZXing.Common;
      
      
      [AddComponentMenu("System/VuforiaCamera")]
      public class VuforiaCamera : MonoBehaviour
      {    
      private bool cameraInitialized;
      
      private BarcodeReader barCodeReader;
      private bool isDecoding = false;
      
      void Start()
      {        
          barCodeReader = new BarcodeReader();
          StartCoroutine(InitializeCamera());
      }
      
      private IEnumerator InitializeCamera()
      {
          // Waiting a little seem to avoid the Vuforia's crashes.
          yield return new WaitForSeconds(1.25f);
      
          // var isFrameFormatSet = CameraDevice.Instance.SetFrameFormat(Image.PIXEL_FORMAT.RGB888, true);
          // Debug.Log(String.Format("FormatSet : {0}", isFrameFormatSet));
      
          // Force autofocus.
          var isAutoFocus = CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
          if (!isAutoFocus)
          {
              CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
          }
          Debug.Log(String.Format("AutoFocus : {0}", isAutoFocus));
          cameraInitialized = true;
      }
      
      private void Update()
      {
          if (cameraInitialized && !isDecoding)
          {
              try
              {
                  var cameraFeed = CameraDevice.Instance.GetCameraImage(Image.PIXEL_FORMAT.RGB888);
      
                  if (cameraFeed == null)
                  {
                      return;
                  }
                  ThreadPool.QueueUserWorkItem(new WaitCallback(DecodeQr), cameraFeed);
      
              }
              catch (Exception e)
              {
                  Debug.LogError(e.Message);
              }
          }
      }
      
      private void DecodeQr(object state){
          isDecoding = true;
          var cameraFeed = (Image)state;
          var data = barCodeReader.Decode(cameraFeed.Pixels, cameraFeed.BufferWidth, cameraFeed.BufferHeight, RGBLuminanceSource.BitmapFormat.RGB24);
          if (data != null)
              {
              // QRCode detected.
                  isDecoding = false;
              }
          else
              {
                  isDecoding = false;
                  Debug.Log("No QR code detected !");
              }
      }    
      }
      

      【讨论】:

      • 经过测试,我注意到在 iOS 上使用 ThreadPool.QueueUserWorkItem 会不断堆叠退出 QR 场景后未关闭的工作线程并消耗 CPU 功率。在进入和退出 QR 场景几次后,这最终导致应用程序挂起。有没有办法手动关闭/中止这些线程?
      • @Ruslan Leshchenko 我得到 cameraFeed=null,我也尝试了不同的图像格式,不幸的是没有工作
      • @Nandha 猜你的相机有问题。很遗憾帮不上忙。
      • 这里我需要提一下,我已将图像格式更改为灰度,而且我已经测试了为 android 制作构建但无法正常工作。