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中,将红点对齐,可以发现绿点也是对齐的,只有一张图例外,右上角未对齐,差别也不大:
由此可见,这个对齐关系比较稳定,可以只计算一次,把结果存储起来,坐标变换时,查表就行了。