Rilevamento di codici a matriceQR code tracking

HoloLens 2 è in grado di rilevare i codici a matrice nell'ambiente attorno al visore VR, stabilendo un sistema di coordinate nella posizione reale di ciascun codice.HoloLens 2 can detect QR codes in the environment around the headset, establishing a coordinate system at each code's real-world location.

Supporto di dispositiviDevice support

FeatureFeature HoloLens (prima generazione)HoloLens (first gen)HoloLens 2HoloLens 2 Visori VR immersiveImmersive headsets
Rilevamento del codice a matriceQR code detection ✔️✔️✔️✔️

Nota

Il rilevamento del codice a matrice con auricolari a realtà mista di Windows su PC desktop è supportato in Windows 10 versione 2004 e successive.QR code tracking with immersive Windows Mixed Reality headsets on desktop PCs is supported on Windows 10 Version 2004 and higher. Usare l'API Microsoft. MixedReality. QRCodeWatcher. non supportata () per determinare se la funzionalità è supportata nel dispositivo corrente.Use the Microsoft.MixedReality.QRCodeWatcher.IsSupported() API to determine whether the feature is supported on the current device.

Recupero del pacchetto QRGetting the QR package

È possibile scaricare il pacchetto NuGet per il rilevamento del codice QR qui.You can download the NuGet package for QR code detection here.

Rilevamento di codici QRDetecting QR codes

Aggiunta della funzionalità webcamAdding the webcam capability

È necessario aggiungere la funzionalità webcam al manifesto per rilevare i codici QR.You'll need to add the capability webcam to your manifest to detect QR codes. Questa funzionalità è necessaria perché i dati nei codici rilevati nell'ambiente dell'utente possono contenere informazioni riservate.This capability is required as the data within detected codes in the user's environment may contain sensitive information.

È possibile richiedere l'autorizzazione chiamando QRCodeWatcher.RequestAccessAsync() :Permission can be requested by calling QRCodeWatcher.RequestAccessAsync():

C#C#:

await QRCodeWatcher.RequestAccessAsync();

C++C++:

co_await QRCodeWatcher.RequestAccessAsync();

Prima di creare un oggetto QRCodeWatcher, è necessario richiedere l'autorizzazione.Permission must be requested before you construct a QRCodeWatcher object.

Sebbene il rilevamento del codice a matrice richieda la webcam funzionalità, il rilevamento si verifica usando le fotocamere di rilevamento del dispositivo.While QR code detection requires the webcam capability, the detection occurs using the device's tracking cameras. Questo fornisce un rilevamento più ampio FOV e una migliore durata della batteria rispetto al rilevamento con la fotocamera Photo/video (PV) del dispositivo.This provides a wider detection FOV and better battery life compared to detection with the device's photo/video (PV) camera.

Rilevamento di codici QR in UnityDetecting QR codes in Unity

È possibile usare l'API di rilevamento del codice a matrice in Unity senza importare MRTK installando il pacchetto NuGet usando NuGet per Unity.You can use the QR code detection API in Unity without importing MRTK by installing the NuGet package using NuGet for Unity. Per avere un'idea del funzionamento, scaricare l' app Unity di esempio.If you want to get a feel for how it works, download the sample Unity app. L'app di esempio include esempi per la visualizzazione di un quadrato olografico su codici QR e dati associati, ad esempio GUID, dimensioni fisiche, timestamp e dati decodificati.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.

Rilevamento di codici QR in 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
        }
    }
};

Recupero del sistema di coordinate per un codice a matriceGetting the coordinate system for a QR code

Ogni codice QR rilevato espone un sistema di coordinate spaziali allineato al codice a matrice nell'angolo superiore sinistro del quadrato di rilevamento rapido in alto a sinistra: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:

Sistema di coordinate del codice a matrice

Quando si usa direttamente il QR SDK, l'asse Z punta alla carta (non mostrata): quando viene convertito in coordinate Unity, l'asse Z punta all'esterno della carta ed è a sinistra.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.

Il SpatialCoordinateSystem del codice a matrice viene allineato come illustrato.A QR code's SpatialCoordinateSystem aligns as shown. È possibile ottenere il sistema di coordinate dalla piattaforma chiamando SpatialGraphInteropPreview:: CreateCoordinateSystemForNode e passando il SpatialGraphNodeId del codice.You can get the coordinate system from the platform by calling SpatialGraphInteropPreview::CreateCoordinateSystemForNode and passing in the code's SpatialGraphNodeId.

Nel codice C++ riportato di seguito viene illustrato come creare un rettangolo e posizionarlo utilizzando il sistema di coordinate del codice a matrice: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;
}

È possibile utilizzare le dimensioni fisiche per creare il rettangolo QR:You can use the physical size to create the QR rectangle:

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

Il sistema di coordinate può essere usato per creare il codice a matrice o per alleghire gli ologrammi al percorso: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());

Il QRCodeAddedHandler potrebbe avere un aspetto simile al seguente: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);
}

Procedure consigliate per il rilevamento del codice a matriceBest practices for QR code detection

Zone tranquille intorno ai codici QRQuiet zones around QR Codes

Per la lettura corretta, i codici a matrice richiedono un margine intorno a tutti i lati del codice.To be read correctly, QR codes require a margin around all sides of the code. Questo margine non deve contenere contenuto stampato e deve essere costituito da quattro moduli (un singolo quadrato nero nel codice).This margin must not contain any printed content and should be four modules (a single black square in the code) wide.

La specifica QR contiene altre informazioni sulle zone tranquile.The QR spec contains more information about quiet zones.

Illuminazione e sfondoLighting and backdrop

La qualità del rilevamento del codice a matrice è soggetta a variazioni di illuminazione e sfondo.QR code detection quality is susceptible to varying illumination and backdrop.

In una scena con illuminazione luminosa stampare un codice nero su uno sfondo grigio.In a scene with bright lighting, print a code that is black on a gray background. In caso contrario, stampare un codice a matrice nero su uno sfondo bianco.Otherwise, print a black QR code on a white background.

Se lo sfondo del codice è scuro, provare a usare un codice nero in grigio se la frequenza di rilevamento è bassa.If the backdrop to the code is dark, try a black on gray code if your detection rate is low. Se lo sfondo è relativamente chiaro, un codice normale dovrebbe funzionare correttamente.If the backdrop is relatively light, a regular code should work fine.

Dimensioni dei codici QRSize of QR codes

I dispositivi di realtà mista di Windows non funzionano con codici a matrice con lati inferiori a 5 cm.Windows Mixed Reality devices don't work with QR codes with sides smaller than 5 cm each.

Per i codici QR compresi tra 5 cm e 10 cm di lunghezza, è necessario essere abbastanza vicini per rilevare il codice.For QR codes between 5 cm and 10-cm length sides, you must be fairly close to detect the code. Sarà inoltre necessario più tempo per rilevare i codici in questa dimensione.It will also take longer to detect codes at this size.

Il tempo esatto per rilevare i codici dipende non solo dalle dimensioni dei codici a matrice, ma da quanto manca il codice.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. Lo spostamento più vicino al codice consente di compensare i problemi con le dimensioni.Moving closer to the code will help offset issues with size.

Posizione angolare e distanza dal codice a matriceDistance and angular position from the QR code

Le videocamere di rilevamento possono rilevare solo un certo livello di dettaglio.The tracking cameras can only detect a certain level of detail. Per i codici piccoli, < 10 cm lungo i lati, è necessario essere abbastanza vicini.For small codes - < 10 cm along the sides - you must be fairly close. Per un codice a matrice di versione 1 variabile da 10 cm a 25 cm di larghezza, la distanza di rilevamento minima varia da 0,15 metri a 0,5 metri.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.

La distanza di rilevamento per le dimensioni aumenta in modo lineare.The detection distance for size increases linearly.

Il rilevamento a matrice funziona con un intervallo di angoli + = 45 deg per garantire la corretta risoluzione per il rilevamento del codice.QR detection works with a range of angles += 45 deg to ensure we have proper resolution to detect the code.

Codici QR con logoQR codes with logos

I codici QR con logo non sono stati testati e non sono attualmente supportati.QR codes with logos haven't been tested and are currently unsupported.

Gestione dei dati del codice QRManaging QR code data

I dispositivi di realtà mista Windows rilevano codici QR a livello di sistema nel driver.Windows Mixed Reality devices detect QR codes at the system level in the driver. Quando il dispositivo viene riavviato, i codici QR rilevati vengono eliminati e verranno rilevati nuovamente come nuovi oggetti la volta successiva.When the device is rebooted, the detected QR codes are gone and will be redetected as new objects next time.

Si consiglia di configurare l'app in modo da ignorare i codici QR precedenti a un timestamp specifico.We recommend configuring your app to ignore QR codes older than a specific timestamp. Attualmente, l'API non supporta la cancellazione della cronologia del codice QR.Currently, the API doesn't support clearing QR code history.

Posizionamento del codice a matrice in uno spazioQR code placement in a space

Per consigli su dove e come collocare i codici QR, vedere considerazioni sull'ambiente per HoloLens.For recommendations on where and how to place QR codes, refer to Environment considerations for HoloLens.

Riferimento all'API QRQR 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,
    }
}

Vedere ancheSee also