🎃

.NETでAzureKinect・RealSenseを使う

2023/03/04に公開約3,500字

モチベ

  • C#で深度カメラ(AzureKinect, RealSenseなど)が使いたくなる場面があるやもしれませぬ。
  • 公式SDKでC++をラップしたライブラリが提供されていますが,ちょっと取っつきにくい感じを醸しています。
  • そこで,一般的なカメラと共通したインターフェースで深度カメラを使えるようにしてみました。

https://github.com/husty530/Husty-public

  • NuGetで以下のパッケージを提供しています。いずれも.NET7をターゲットにしているので,それ以下のプラットフォームで使いたい場合はソースコードをコピペしてください。
    • Husty.OpenCvSharp
    • Husty.OpenCvSharp.AzureKinect
    • Husty.OpenCvSharp.RealSense

解説

インターフェース

using OpenCvSharp;

namespace Husty.OpenCvSharp.ImageStream;

public record Properties(VideoCaptureProperties Key, double Value);

public interface IImageStream<TImage> : IDisposable
{
    public int Fps { get; }
    public int Channels { get; }
    public Size FrameSize { get; }
    public IObservable<TImage> ImageSequence { get; }
    public TImage Read();
}
  • 以下,コンストラクタで各カメラの初期化を個別処理します。

普通のカメラ(OpenCVのVideoCaptureで捌けるもの)

public CameraStream(int src, IEnumerable<Properties> properties = null);
  • 簡単ですね。カメラ番号とOpenCVのVideoCapturePropertiesを好みで指定します。

ビデオファイル

public VideoStream(string src, IEnumerable<Properties> properties = null);
  • 同じですね。

AzureKinect

public CameraStream(DeviceConfiguration config, int id = 0, MatchingBase align = MatchingBase.Color);
public CameraStream(int id = 0, MatchingBase align = MatchingBase.Color);
  • オーバーロードが2つあります。
  • DeviceConfigurationを指定しない2つ目のコンストラクタでは以下のように初期化されます。
{
   ColorFormat = ImageFormat.ColorBGRA32,
   ColorResolution = ColorResolution.R720p,
   DepthMode = DepthMode.WFOV_2x2Binned,
   SynchronizedImagesOnly = true,
   CameraFPS = FPS.FPS30
}

RealSense

public CameraStream(Size size, MatchingBase align = MatchingBase.Color, int fps = 30, bool disparityTransform = true, bool spatialFilter = true, bool temporalFilter = true, bool holeFillingFilter = true);
  • sizeは機器のバージョンによって指定できるものが異なります。間違えると無言のエラーとなるのでお気をつけください。選択可能なサイズは公式のRealSenseViewerなどで確認できます。

  • また,ここまで作ったからには当然,深度カメラの録画/再生機能も用意してございます。

  • コード

利用例

using System.Reactive.Linq;
using OpenCvSharp;
using Husty.Extensions;
using Husty.OpenCvSharp.ImageStream;
using Husty.OpenCvSharp.ThreeDimensionalImaging;
using Kinect = Husty.OpenCvSharp.AzureKinect;
using RealSense = Husty.OpenCvSharp.RealSense;

IImageStream<BgrXyzImage> camera = new RealSense.CameraStream(new(640, 360));
// IImageStream<BgrXyzImage> camera = new Kinect.CameraStream();

var connector = camera
    .ImageSequence
    .TimeInterval()
    .Subscribe(v =>
    {
        Console.WriteLine((int)v.Interval.TotalMilliseconds);
	using var d8 = v.Value.GetDepth8(300, 5000);
        Cv2.ImShow("COLOR", v.Value.Bgr);
	Cv2.ImShow("DEPTH", d8);
        Cv2.WaitKey(1);
    });

Console.WriteLine("Press Enter key to exit...");
ConsoleEx.WaitKey(ConsoleKey.Enter);
connector.Dispose();
camera.Dispose();

Discussion

ログインするとコメントできます