QR コードの追跡 (C# と C++)
ここから始める前に、「QR コード追跡の概要」の記事に目を通すことをお勧めします。この記事には、概要、デバイス サポートの表、ベスト プラクティスが含まれています。
QR パッケージを取得する
QR コード検出用の NuGet パッケージは、こちらからダウンロードできます。
QR コードを検出する
Web カメラ機能を追加する
QR コードを検出するには、マニフェストに webcam
機能を追加する必要があります。 ユーザーの環境で検出されたコード内のデータに機密情報が含まれている可能性があるため、この機能が必要です。
アクセス許可を要求するには、QRCodeWatcher.RequestAccessAsync()
を呼び出します。
C#:
await QRCodeWatcher.RequestAccessAsync();
C++:
co_await QRCodeWatcher.RequestAccessAsync();
QRCodeWatcher オブジェクトを作成する前に、アクセス許可を要求する必要があります。
QR コードの検出には webcam
機能が必要ですが、検出はデバイスの追跡カメラを使用して行われます。 これにより、デバイスの写真/ビデオ (PV) カメラを使用した検出と比較して、より広い検出 FOV とバッテリー寿命の向上が可能になります。
C++ で QR コードを検出する
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 コードの座標系を取得する
検出された各 QR コードにより、左上の高速検出正方形の左上隅にある QR コードと一致する空間座標系が公開されます。
QR SDK を直接使用する場合は、Z 軸が用紙 (非表示) を示しています。
QR コードの SpatialCoordinateSystem は、次のように配置されます。 SpatialGraphInteropPreview::CreateCoordinateSystemForNode を呼び出し、コードの SpatialGraphNodeId を渡すことによって、プラットフォームから座標系を取得できます。
次の C++ コードは、四角形を作成し、QR コードの座標系を使用して配置する方法を示しています。
// 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 四角形を作成できます。
std::vector<float3> qrVertices = CreateRectangle(code.PhysicalSideLength(), code.PhysicalSideLength());
座標系を使用すると、QR コードを描画したり、その場所にホログラムをアタッチしたりできます。
using namespace winrt::Windows::Perception::Spatial;
using namespace winrt::Windows::Perception::Spatial::Preview;
SpatialCoordinateSystem qrCoordinateSystem = SpatialGraphInteropPreview::CreateCoordinateSystemForNode(code.SpatialGraphNodeId());
QRCodeAddedHandler は、次のような場合があります。
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 コード追跡 API リファレンス
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,
}
}