Kinect的彩圖和景深圖兩個圖是不對齊的,DepthImageFrame提供了MapToColorImagePoint方法用以計算指定景深圖坐標所對應的彩圖點。原以為從景深圖坐標到彩圖坐標是仿射變換關系,因此,在對齊時,在景深圖指定了三個點(0,0),(0,400),(400,0),計算這三個點對應的彩圖坐標,然后再求出變換矩陣,進行坐標變換。昨天客戶反應,當人物走到攝像頭的右側時,會出現圖像錯位現象:
懷疑是否是景深圖和彩圖對齊的問題。下面進行詳細測試,對景深圖每隔10個像素點進行采樣,計算對應的彩圖坐標,繪制在同一張圖上,景深圖坐標為紅點,彩圖坐標為綠點。
匹配代碼:
private List<Point> points =
new List<Point>();
for ( int x = 0; x < 640; x += 10)
{
for ( int y = 0; y < 480; y += 10)
{
ColorImagePoint p = depthImageFrame.MapToColorImagePoint(x, y, ColorImageFormat.RgbResolution640x480Fps30);
points.Add( new Point(p.X, p.Y));
points.Add( new Point(x, y));
}
}
for ( int x = 0; x < 640; x += 10)
{
for ( int y = 0; y < 480; y += 10)
{
ColorImagePoint p = depthImageFrame.MapToColorImagePoint(x, y, ColorImageFormat.RgbResolution640x480Fps30);
points.Add( new Point(p.X, p.Y));
points.Add( new Point(x, y));
}
}
繪制代碼:
Point[] list = points.ToArray();
Bitmap match = new Bitmap( 640, 480);
Graphics g = Graphics.FromImage(match);
Pen pen1 = new Pen(Color.Red, 2);
Pen pen2 = new Pen(Color.Green, 2);
int i = 0;
foreach (Point p in list)
{
i++;
if (i % 2 == 0)
{
g.DrawLine(pen1, p, new Point(p.X + 1, p.Y + 1));
}
else
{
g.DrawLine(pen2, p, new Point(p.X + 1, p.Y + 1));
}
}
match.Save( " match_ " + timeString + " .png ", System.Drawing.Imaging.ImageFormat.Png);
Bitmap match = new Bitmap( 640, 480);
Graphics g = Graphics.FromImage(match);
Pen pen1 = new Pen(Color.Red, 2);
Pen pen2 = new Pen(Color.Green, 2);
int i = 0;
foreach (Point p in list)
{
i++;
if (i % 2 == 0)
{
g.DrawLine(pen1, p, new Point(p.X + 1, p.Y + 1));
}
else
{
g.DrawLine(pen2, p, new Point(p.X + 1, p.Y + 1));
}
}
match.Save( " match_ " + timeString + " .png ", System.Drawing.Imaging.ImageFormat.Png);
其中,timeString 記錄的是當前時間。
結果如下:

可以看出,它是一個很復雜的場,用肉眼可以看出有16個特殊位置:
不去深究這十六個點時什么。從上面可以看出,這個變換不是仿射變換,無法使用仿射變換矩陣。應該進行逐點變換。KinectSensor類提供了逐點變換的方法:MapDepthFrameToColorFrame。
現在需要了解,景深圖和彩圖的坐標變換關系是穩定的還是不穩定的呢(隨着時間推移,這個變換關系會不會發生改變?),如果是穩定的,我們只需要求一次變換,如果不是穩定的,則需要每次都要求解變換。
將兩個不同時間點生成的匹配圖拖到photoshop中,將紅點對齊,可以發現綠點也是對齊的,只有一張圖例外,右上角未對齊,差別也不大:

由此可見,這個對齊關系比較穩定,可以只計算一次,把結果存儲起來,坐標變換時,查表就行了。