Kinect 深度マップをメートル単位の距離に変換しようとしています。問題は、デプスマップ値「1080」とその周辺では、分母の項が「0」に非常に近くなるため、距離が大きすぎることです。「1090」を超える値の場合、距離は負になります。
if (depthValue < 2047)
{
depthM = 1.0 / (depthValue*-0.0030711016 + 3.3309495161);
}
正解は、実際には質問に対するコメントです。与えられた数値は、実際にはミリメートル単位の距離です。この数値を取得するには、スケルトン ジョイントを使用して DepthImageFrame の MapFromSkeletonPoint を呼び出すか、生の short 値を DepthImageFrame.PlayerIndexBitmaskWidth だけ右にシフトする必要があります。
例: スケルトン
using (var skeletonFrame= e.OpenSkeletonFrame())
using (var depthFrame = e.OpenDepthImageFrame())
{
skeletonFrame.CopySkeletonDataTo(skeletons);
var skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
foreach (var skeleton in skeletons)
{
if (skeleton.TrackingState != SkeletonTrackingState.Tracked) continue;
var head = skeleton.Joints[JointType.Head];
if (head.TrackingState == JointTrackingState.NotTracked) continue;
var depthImagePoint = depthFrame.MapFromSkeletonPoint(head.Position);
int depthInMillimeters = depthImagePoint.Depth; // TADA!
}
}
例:シフト
using (var depthFrame = e.OpenDepthImageFrame())
{
var depthArray = new short[depthFrame.PixelDataLength];
depthFrame.CopyPixelDataTo(depthArray);
for (int i = 0; i < depthArray.Length; i++) {
int depthInMillimeters =
depthArray[i] >> DepthImageFrame.PlayerIndexBitmaskWidth;
// TADAx2!
}
以下の元の解決策は正しくありません。
この記事の内容に基づく - http://openkinect.org/wiki/Imaging_Information :
if (depthValue <= 2047) {
depthM = 0.1236 * Math.Tan(depthValue / 2842.5 + 1.1863);
}
古い非アクティブな質問ですが、とにかくこれが私にとってうまくいったことです。私はkinectの古いモデル(XBOX360 + PC削減用の1414)を持っており、最近いくつかのコードと測定を行う時間がありました:
私の生データは10/11/12/13ビットではなく16ビットです!!!
したがって、おそらくあなたのデータは非常に似ています。測定された最小距離は~0.95m
不明な最大距離 (テストに十分な大きさの領域がありません) であり、有効な最小値は6408 ... ~0.95m
センサーからのものです。別の有効な値は15800 ... ~2.5m
、補間用のセンサーからのものです
メートルへの単純な (線形) 変換
float z,m=(2.5-0.9)/(15800.0-6408.0);
WORD raw;
raw=... raw depth form camera/image;
z=0.0;
if ((raw>=6408)&&(raw< 0xFFF0))
z=0.9+(float(raw-6408)*m);
// here z is range in [m] or 0 for invalid depth
もっと時間があれば、直線性をチェックしてより正確にします
そのためには、より正確な距離測定のために、より良い測定とセットアップ作業領域のためのプログラミングを行う必要があります。より正確な定数は、必要に応じてコサイン補正を追加することがあります。デバイス/ドライバーがそれ自体を作成するか、測定する必要がないかはわかりません。私がそれに到達すると、私の答えが更新されますが、私は非常に怠惰なので、しばらく時間がかかることがあります...
[編集 1] ジオメトリ測定のセットアップとコードの変更
を行ったので、より正確な新しい結論を以下に示します。
if (raw==0x0000) z=0.0;
else if (p.raw>=0x8000) p.z=4.0;
else p.z=0.8+(float(p.raw-6576)*0.00012115165336374002280501710376283);
raw
データはドライバーまたはkinect自体によって既にコサイン補正されているためraw
、センサーからの垂直距離を表します。raw
データは直線から垂直までの距離 (少なくとも 0.8 ~ 2.0 m の範囲) であり、より正確な測定後の深度範囲は<0.8 - 4.0> [m]
. 以前の測定は不正確でした。
raw = 0
値が近すぎる値
raw >= 32768
が遠すぎる / 不明な値、または他の何か (可能性はもっとあります)