UWPアプリからOpenCVしてみる(その2)

矢野です。UWPアプリからOpenCVを使う話の決着をつけておきます。 Visual Studioを起動して、メインページにボタンを追加します。 
NuGetを使って、OpenCvSharp(OpenCvSharp4, OpenCvSharp4.runtime.uwp)をインストールします。 ボタンのクリックイベントハンドラ(find_Click)に、カメラからのキャプチャ、データ変換、ARマーカーの検出、結果を表示という流れでコードを書いていきます。
private async void find_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
    ImageEncodingProperties encProp = ImageEncodingProperties.CreateBmp();

    var source = captureElement.Source;

    SoftwareBitmap bitmap = null;
    using (var captureStream = new InMemoryRandomAccessStream())
    {
        await source.CapturePhotoToStreamAsync(encProp, captureStream);
        await captureStream.FlushAsync();
        captureStream.Seek(0);

        var decoder = await BitmapDecoder.CreateAsync(captureStream);
        bitmap = await decoder.GetSoftwareBitmapAsync(
            BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
    }

    Mat mat = null;
    using (var stream = new InMemoryRandomAccessStream())
    {
        var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, stream);
        encoder.SetSoftwareBitmap(bitmap);
        await encoder.FlushAsync();

        mat = Mat.FromStream(stream.AsStreamForRead(), ImreadModes.Color);
    }

    var grayMat = new Mat();
    Cv2.CvtColor(mat, grayMat, ColorConversionCodes.BGR2GRAY);

    CvAruco.DetectMarkers(grayMat,
        CvAruco.GetPredefinedDictionary(PredefinedDictionaryName.Dict4X4_50),
        out Point2f[][] corners, out int[] ids, DetectorParameters.Create(), out Point2f[][] rejectedImgPoints);

    CvAruco.DrawDetectedMarkers(mat, corners, ids);

    using (var stream = new MemoryStream())
    {
        mat.WriteToStream(stream);
        using (var raStream = stream.AsRandomAccessStream())
        {
            var decoder = await BitmapDecoder.CreateAsync(raStream);
            bitmap = await decoder.GetSoftwareBitmapAsync(
                BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
        }
    }

    var imageSource = new SoftwareBitmapSource();
    await imageSource.SetBitmapAsync(bitmap);
    image.Source = imageSource;
}
OpenCvSharpは優れたライブラリで、.NETアプリケーションからOpenCVを使いやすくラップしてくれています。おかげでOpenCVでのARマーカー検出、描画は難しくありませんでした。 ところが、それ以前にUWPのSoftwareBitmapとOpenCVのMat型の相互の変換についてはなかなか消化することができず、あちこちのオンラインドキュメントやブログやフォーラムを何度も何度も巡回しつつ、試行錯誤しつつ行ったり来たりを繰り返してようやくそれらしい形にたどり着きました。 あまりそんなことばっかりやっているわけにはいきませんが、ある程度余裕を持て、藻掻いて、悩む時間も時には大事ですね。
これでもって改めて前回の記事をカメラで撮ってみる(横着)と、無事にARマーカーとそのID(3)が認識されていることが確認できました。