Отслеживание QR-кодаQR code tracking

HoloLens 2 может обнаруживать QR-коды в среде вокруг гарнитуры, определяя систему координат в реальном расположении каждого кода.HoloLens 2 can detect QR codes in the environment around the headset, establishing a coordinate system at each code's real-world location.

Поддержка устройствDevice support

КомпонентFeature HoloLens (первый общий)HoloLens (first gen)HoloLens 2HoloLens 2 Иммерсивные гарнитурыImmersive headsets
Обнаружение QR-кодаQR code detection ✔️✔️✔️✔️

Примечание

Отслеживание QR-кодов с помощью впечатляющих головных телефонов Windows Mixed Reality на настольных компьютерах поддерживается в Windows 10 версии 2004 и более поздних версиях.QR code tracking with immersive Windows Mixed Reality headsets on desktop PCs is supported on Windows 10 Version 2004 and higher. Используйте API Microsoft. Микседреалити. Кркодеватчер. support (), чтобы определить, поддерживается ли эта функция на текущем устройстве.Use the Microsoft.MixedReality.QRCodeWatcher.IsSupported() API to determine whether the feature is supported on the current device.

Получение QR-пакетаGetting the QR package

Пакет NuGet для обнаружения QR-кода можно скачать здесь.You can download the NuGet package for QR code detection here.

Обнаружение QR-кодовDetecting QR codes

Добавление возможности веб-камерыAdding the webcam capability

Чтобы обнаружить QR-коды, необходимо добавить в webcam Манифест возможность.You'll need to add the capability webcam to your manifest to detect QR codes. Эта возможность необходима, так как данные в обнаруженных кодах в пользовательской среде могут содержать конфиденциальные сведения.This capability is required as the data within detected codes in the user's environment may contain sensitive information.

Разрешение можно запросить, вызвав QRCodeWatcher.RequestAccessAsync() :Permission can be requested by calling QRCodeWatcher.RequestAccessAsync():

СмC#:

await QRCodeWatcher.RequestAccessAsync();

C++C++:

co_await QRCodeWatcher.RequestAccessAsync();

Разрешение должно быть запрошено до создания объекта Кркодеватчер.Permission must be requested before you construct a QRCodeWatcher object.

Хотя для обнаружения QR-кодов требуется webcam возможность, обнаружение осуществляется с помощью камер отслеживания устройства.While QR code detection requires the webcam capability, the detection occurs using the device's tracking cameras. Это обеспечивает более широкое ФОВное обнаружение и повышает время работы аккумулятора по сравнению с обнаружением с помощью камеры устройства и видео (ПС).This provides a wider detection FOV and better battery life compared to detection with the device's photo/video (PV) camera.

Обнаружение QR-кодов в UnityDetecting QR codes in Unity

API обнаружения QR-кода можно использовать в Unity без импорта МРТК, установив пакет NuGet с помощью NuGet для Unity.You can use the QR code detection API in Unity without importing MRTK by installing the NuGet package using NuGet for Unity. Если вы хотите узнать, как это работает, скачайте пример приложения Unity.If you want to get a feel for how it works, download the sample Unity app. Пример приложения содержит примеры для отображения с holographic-го квадрата по QR кодам и связанным данным, таким как GUID, физический размер, метка времени и декодированные данные.The sample app has examples for displaying a holographic square over QR codes and associated data such as GUID, physical size, timestamp, and decoded data.

Обнаружение QR-кодов в C++Detecting QR codes in C++

using namespace winrt::Windows::Foundation;
using namespace winrt::Microsoft::MixedReality::QR;

class QRListHelper
{
public:
    QRListHelper(MyApplication& app) :
        m_app(app)
    {}

    IAsyncAction SetUpQRCodes()
    {
        if (QRCodeWatcher::IsSupported())
        {
            QRCodeWatcherAccessStatus status = co_await QRCodeWatcher::RequestAccessAsync();
            InitializeQR(status);
        }
    }

private:
    void OnAddedQRCode(const IInspectable&, const QRCodeAddedEventArgs& args)
    {
        m_app.OnAddedQRCode(args);
    }

    void OnUpdatedQRCode(const IInspectable&, const QRCodeUpdatedEventArgs& args)
    {
        m_app.OnUpdatedQRCode(args);
    }

    void OnEnumerationComplete(const IInspectable&, const IInspectable&)
    {
        m_app.OnEnumerationComplete();
    }

    MyApplication& m_app;
    QRCodeWatcher m_qrWatcher{ nullptr };

    void InitializeQR(QRCodeWatcherAccessStatus status)
    {
        if (status == QRCodeWatcherAccessStatus::Allowed)
        {
            m_qrWatcher = QRCodeWatcher();
            m_qrWatcher.Added({ this, &QRListHelper::OnAddedQRCode });
            m_qrWatcher.Updated({ this, &QRListHelper::OnUpdatedQRCode });
            m_qrWatcher.EnumerationCompleted({ this, &QRListHelper::OnEnumerationComplete });
            m_qrWatcher.Start();
        }
        else
        {
            // Permission denied by system or user
            // Handle the failures
        }
    }
};

Получение системы координат для QR-кодаGetting the coordinate system for a QR code

Каждый обнаруженный QR-код предоставляет пространственное координатную систему , согласованную с QR-кодом в левом верхнем углу квадрата быстрого обнаружения в верхней левой части:Each detected QR code exposes a spatial coordinate system aligned with the QR code at the top-left corner of the fast detection square in the top left:

Система координат QR-кода

При непосредственном использовании QR-пакета SDK ось Z указывает на бумагу (не показано) — при преобразовании в координаты Unity точки оси Z находятся за пределами бумаги и остаются в левой части.When directly using the QR SDK, the Z-axis is pointing into the paper (not shown) - when converted into Unity coordinates, the Z-axis points out of the paper and is left-handed.

Спатиалкурдинатесистем QR-кода выстраивается так, как показано.A QR code's SpatialCoordinateSystem aligns as shown. Вы можете получить систему координат из платформы, вызвав спатиалграфинтероппревиев:: креатекурдинатесистемфорноде и передав спатиалграфнодеид кода.You can get the coordinate system from the platform by calling SpatialGraphInteropPreview::CreateCoordinateSystemForNode and passing in the code's SpatialGraphNodeId.

В приведенном ниже коде C++ показано, как создать прямоугольник и разместить его с помощью системы координат QR-кода:The C++ code below shows how to create a rectangle and place it using the QR code's coordinate system:

// Creates a 2D rectangle in the x-y plane, with the specified properties.
std::vector<float3> MyApplication::CreateRectangle(float width, float height)
{
    std::vector<float3> vertices(4);

    vertices[0] = { 0, 0, 0 };
    vertices[1] = { width, 0, 0 };
    vertices[2] = { width, height, 0 };
    vertices[3] = { 0, height, 0 };

    return vertices;
}

Для создания QR-прямоугольника можно использовать физический размер:You can use the physical size to create the QR rectangle:

std::vector<float3> qrVertices = CreateRectangle(code.PhysicalSideLength(), code.PhysicalSideLength()); 

Систему координат можно использовать для рисования QR-кода или прикрепления голограмм к расположению:The coordinate system can be used to draw the QR code or attach holograms to the location:

using namespace winrt::Windows::Perception::Spatial;
using namespace winrt::Windows::Perception::Spatial::Preview;
SpatialCoordinateSystem qrCoordinateSystem = SpatialGraphInteropPreview::CreateCoordinateSystemForNode(code.SpatialGraphNodeId());

В целом, ваш кркодеаддедхандлер может выглядеть примерно так:Altogether, your QRCodeAddedHandler may look something like this:

void MyApplication::OnAddedQRCode(const QRCodeAddedEventArgs& args)
{
    QRCode code = args.Code();
    std::vector<float3> qrVertices = CreateRectangle(code.PhysicalSideLength(), code.PhysicalSideLength());
    std::vector<unsigned short> qrCodeIndices = TriangulatePoints(qrVertices);
    XMFLOAT3 qrAreaColor = XMFLOAT3(DirectX::Colors::Aqua);

    SpatialCoordinateSystem qrCoordinateSystem = SpatialGraphInteropPreview::CreateCoordinateSystemForNode(code.SpatialGraphNodeId());
    std::shared_ptr<SceneObject> m_qrShape =
        std::make_shared<SceneObject>(
            m_deviceResources,
            qrVertices,
            qrCodeIndices,
            qrAreaColor,
            qrCoordinateSystem);

    m_sceneController->AddSceneObject(m_qrShape);
}

Рекомендации по обнаружению QR-кодаBest practices for QR code detection

Зоны без кавычек вокруг QR-кодовQuiet zones around QR Codes

Для правильного чтения QR-коды занимают поля вокруг всех сторон кода.To be read correctly, QR codes require a margin around all sides of the code. Это поле не должно содержать ни одного печатного содержимого и должно состоять из четырех модулей (один черный квадрат в коде).This margin must not contain any printed content and should be four modules (a single black square in the code) wide.

QR-спецификация содержит дополнительные сведения о зонах «тихий».The QR spec contains more information about quiet zones.

Освещение и фонLighting and backdrop

Качество обнаружения QR-кодов является уязвимым для различных освещения и подложки.QR code detection quality is susceptible to varying illumination and backdrop.

В сцене с ярким освещением распечатайте черный цвет на сером фоне.In a scene with bright lighting, print a code that is black on a gray background. В противном случае распечатайте черный QR-код на белом фоне.Otherwise, print a black QR code on a white background.

Если фон кода является темным, попробуйте использовать черный цвет в сером коде, если частота обнаружения мала.If the backdrop to the code is dark, try a black on gray code if your detection rate is low. Если подложка относительно легкая, то обычный код должен работать нормально.If the backdrop is relatively light, a regular code should work fine.

Размер QR-кодовSize of QR codes

Устройства Windows Mixed Reality не работают с QR-кодами с сторонами, меньшими 5 cm.Windows Mixed Reality devices don't work with QR codes with sides smaller than 5 cm each.

Для QR-кодов, которые находятся в диапазоне от 5 до 10 cm, вы должны быть достаточно близки к обнаружению кода.For QR codes between 5 cm and 10-cm length sides, you must be fairly close to detect the code. Для обнаружения кодов с таким размером также потребуется больше времени.It will also take longer to detect codes at this size.

Точное время на обнаружение кодов зависит не только от размера QR-кодов, но от того, насколько далеко вы находитесь вне кода.The exact time to detect codes depends not only on the size of the QR codes, but how far you're away from the code. Переход ближе к коду поможет в смещении проблем с размером.Moving closer to the code will help offset issues with size.

Расстояние и угловое расположение из QR-кодаDistance and angular position from the QR code

Отслеживающие камеры могут обнаруживать только определенный уровень детализации.The tracking cameras can only detect a certain level of detail. Для небольших кодов — < 10 cm вдоль сторон, вы должны быть достаточно близки.For small codes - < 10 cm along the sides - you must be fairly close. Для QR-кода версии 1, отличающегося от 10 cm до 25 сантиметров, минимальное расстояние обнаружения составляет от 0,15 метров до 0,5 метров.For a version 1 QR code varying from 10 cm to 25 cm wide, the minimum detection distance ranges from 0.15 meters to 0.5 meters.

Расстояние обнаружения для размера увеличивается линейно.The detection distance for size increases linearly.

Обнаружение QR работает с диапазоном углов + = 45 град, чтобы обеспечить правильное разрешение для обнаружения кода.QR detection works with a range of angles += 45 deg to ensure we have proper resolution to detect the code.

QR-коды с логотипамиQR codes with logos

QR-коды с логотипами не тестировались и в настоящее время не поддерживаются.QR codes with logos haven't been tested and are currently unsupported.

Управление данными QR-кодаManaging QR code data

Устройства Windows Mixed Reality обнаруживают QR-коды на уровне системы в драйвере.Windows Mixed Reality devices detect QR codes at the system level in the driver. При перезагрузке устройства обнаруженные QR-коды исчезают и будут повторно обнаружены как новые объекты в следующий раз.When the device is rebooted, the detected QR codes are gone and will be redetected as new objects next time.

Мы рекомендуем настроить приложение так, чтобы оно игнорировало QR-коды старше определенной метки времени.We recommend configuring your app to ignore QR codes older than a specific timestamp. В настоящее время API не поддерживает очистку журнала QR-кода.Currently, the API doesn't support clearing QR code history.

Размещение QR-кода в пространствеQR code placement in a space

Рекомендации по месту и способу размещения QR-кодов см. в статье рекомендации по окружению для HoloLens.For recommendations on where and how to place QR codes, refer to Environment considerations for HoloLens.

Справочник по QR-APIQR API reference

namespace Microsoft.MixedReality.QR
{
    /// <summary>
    /// Represents a detected QR code.
    /// </remarks>
    public class QRCode
    {
        /// <summary>
        /// Unique id that identifies this QR code for this session.
        /// </summary>
        public Guid Id { get; }

        /// <summary>
        /// Spatial graph node id for this QR code to create a coordinate system.
        /// </summary>
        public Guid SpatialGraphNodeId { get; }

        /// <summary>
        /// Version of this QR code. Version 1-40 are regular QR codes and M1 to M4 are Micro QR code formats 1-4.
        /// </summary>
        public QRVersion Version { get; }

        /// <summary>
        /// Physical width and height of this QR code in meters.
        /// </summary>
        public float PhysicalSideLength { get; }

        /// <summary>
        /// Decoded QR code data.
        /// </summary>
        public String Data { get; }

        /// <summary>
        /// Size of the RawData of this QR code.
        /// </summary>
        public UInt32 RawDataSize { get; }

        /// <summary>
        /// Gets the error-corrected raw data bytes.
        /// Used when the platform is unable to decode the code's format,
        /// allowing your app to decode as needed.
        /// </summary>
        public void GetRawData(byte[] buffer);

        /// <summary>
        /// The last detected time in 100ns QPC ticks.
        /// </summary>
        public System.TimeSpan SystemRelativeLastDetectedTime { get; }

        /// <summary>
        /// The last detected time.
        /// </summary>
        public System.DateTimeOffset LastDetectedTime { get; }
    }

    /// <summary>
    /// Event arguments for a QRCodeWatcher's Added event.
    /// </summary>
    public class QRCodeAddedEventArgs
    {
        /// <summary>
        /// Gets the QR Code that was added
        /// </summary>
        public QRCode Code { get; }
    }

    /// <summary>
    /// Event arguments for a QRCodeWatcher's Removed event.
    /// </summary>
    public class QRCodeRemovedEventArgs
    {
        /// <summary>
        /// Gets the QR Code that was removed.
        /// </summary>
        public QRCode Code { get; }
    }

    /// <summary>
    /// Event arguments for a QRCodeWatcher's Updated event.
    /// </summary>
    public class QRCodeUpdatedEventArgs
    {
        /// <summary>
        /// Gets the QR Code that was updated.
        /// </summary>
        public QRCode Code { get; }
    }

    /// <summary>
    /// Represents the status of an access request for QR code detection.
    /// </summary>
    public enum QRCodeWatcherAccessStatus
    {
        /// <summary>
        /// The system has denied permission for the app to detect QR codes.
        /// </summary>
        DeniedBySystem = 0,
        /// <summary>
        /// The app has not declared the webcam capability in its manifest.
        /// </summary>
        NotDeclaredByApp = 1,
        /// <summary>
        /// The user has denied permission for the app to detect QR codes.
        /// </summary>
        DeniedByUser = 2,
        /// <summary>
        /// A user prompt is required to get permission to detect QR codes.
        /// </summary>
        UserPromptRequired = 3,
        /// <summary>
        /// The user has given permission to detect QR codes.
        /// </summary>
        Allowed = 4,
    }

    /// <summary>
    /// Detects QR codes in the user's environment.
    /// </summary>
    public class QRCodeWatcher
    {
        /// <summary>
        /// Gets whether QR code detection is supported on the current device.
        /// </summary>
        public static bool IsSupported();

        /// <summary>
        /// Request user consent before using QR code detection.
        /// </summary>
        public static IAsyncOperation<QRCodeWatcherAccessStatus> RequestAccessAsync();

        /// <summary>
        /// Constructs a new QRCodeWatcher.
        /// </summary>
        public QRCodeWatcher();

        /// <summary>
        /// Starts detecting QR codes.
        /// </summary>
        /// <remarks>
        /// Start should only be called once RequestAccessAsync has succeeded.
        /// Start should not be called if QR code detection is not supported.
        /// Check that IsSupported returns true before calling Start.
        /// </remarks>
        public void Start();

        /// <summary>
        /// Stops detecting QR codes.
        /// </summary>
        public void Stop();

        /// <summary>
        /// Get the list of QR codes detected.
        /// </summary>
        /// <remarks>
        /// </remarks>
        public IList<QRCode> GetList();

        /// <summary>
        /// Event representing the addition of a QR Code.
        /// </summary>
        public event EventHandler<QRCodeAddedEventArgs> Added;

        /// <summary>
        /// Event representing the removal of a QR Code.
        /// </summary>
        public event EventHandler<QRCodeRemovedEventArgs> Removed;

        /// <summary>
        /// Event representing the update of a QR Code.
        /// </summary>
        public event EventHandler<QRCodeUpdatedEventArgs> Updated;

        /// <summary>
        /// Event representing the enumeration of QR Codes completing after a Start call.
        /// </summary>
        public event EventHandler<Object> EnumerationCompleted;
    }

    /// <summary>
    /// Version info for QR codes, including Micro QR codes.
    /// </summary>
    public enum QRVersion
    {
        QR1 = 1,
        QR2 = 2,
        QR3 = 3,
        QR4 = 4,
        QR5 = 5,
        QR6 = 6,
        QR7 = 7,
        QR8 = 8,
        QR9 = 9,
        QR10 = 10,
        QR11 = 11,
        QR12 = 12,
        QR13 = 13,
        QR14 = 14,
        QR15 = 15,
        QR16 = 16,
        QR17 = 17,
        QR18 = 18,
        QR19 = 19,
        QR20 = 20,
        QR21 = 21,
        QR22 = 22,
        QR23 = 23,
        QR24 = 24,
        QR25 = 25,
        QR26 = 26,
        QR27 = 27,
        QR28 = 28,
        QR29 = 29,
        QR30 = 30,
        QR31 = 31,
        QR32 = 32,
        QR33 = 33,
        QR34 = 34,
        QR35 = 35,
        QR36 = 36,
        QR37 = 37,
        QR38 = 38,
        QR39 = 39,
        QR40 = 40,
        MicroQRM1 = 41,
        MicroQRM2 = 42,
        MicroQRM3 = 43,
        MicroQRM4 = 44,
    }
}

См. также разделSee also