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