我在哪里可以学习/找到使用OpenCV从Kinect流式传输的手势识别示例?

时间:2010-12-16 05:31:37

标签: algorithm opencv gesture-recognition kinect

我有适用于Windows和MacOSX的Kinect和驱动程序。是否有任何使用OpenCV API从Kinect流式传输的手势识别示例?我试图在Windows和MacOSX中实现与DaVinci prototype on Xbox Kinect类似的功能。

3 个答案:

答案 0 :(得分:15)

您链接中的演示似乎没有使用真正的手势识别。它只是区分两个不同的手位置(打开/关闭),这更容易,并跟踪手的位置。考虑到他在演示中握手的方式(在身体前方,当他们打开时面对kinect),这可能是他正在做的事情。由于您没有精确使用您正在使用的语言,因此我将在openCV中使用C函数名称,但它们在其他语言中应该类似。我还假设您可以从kinect获取深度图(如果使用libfreenect,可能通过回调函数)。

  1. 深度阈值,仅选择足够接近的点(指针)。 您可以自己实现,也可以直接使用openCV来获取二进制图像(带CV_THRESH_BINARY的cvThreshold())。 显示阈值后获得的图像并调整阈值以适合您的配置(尽量避免太靠近kinect,因为此区域有更多干扰)。

  2. 使用cvFindContour获取手的轮廓()

  3. 这是基础。既然你有手的轮廓,根据你想要做什么,你可以采取不同的方向。如果您只想在手动打开和关闭之间进行检测,您可以这样做:

    1. 使用cvConvexHull2()获取手的凸包

    2. 使用cvConvexityDefect()在轮廓和之前获得的凸包上获取凸度缺陷。

    3. 分析凸度缺陷:如果有大的缺陷,手是打开的(因为手指之间的形状是凹的),如果不是手被关闭。

    4. 但你也可以做手指检测!这就是我上周所做的,这不需要太多的努力,可能会提升你的演示!一种便宜但非常可靠的方法是:

      1. 用多边形近似手轮廓。在轮廓上使用cvApproxPoly()。您必须调整精度参数以使多边形尽可能简单但不会将手指混合在一起(大约15个应该非常好,但是使用cvDrawContours()在您的图像上绘制它以检查您获得的内容) 。

      2. 分析轮廓以找到尖锐的凸角。你必须手工完成。这是最棘手的部分,因为:

        • openCV中使用的数据结构起初可能有点令人困惑。如果你对CvSeq结构过于挣扎,cvCvtSeqToArray()可能会有所帮助。
        • 你终于可以做一些(基本的)数学来找到凸角。请记住,您可以使用点积来确定角度的锐度,以及用于区分凸角和凹角的矢量乘积。
      3. 在这里,尖锐的凸角是你的指尖!

      4. 这是一种检测手指的简单算法,但有很多方法可以提升它。例如,您可以尝试在深度图上应用中值滤波器以“平滑”一切,或者尝试使用更精确的多边形近似,然后过滤轮廓以合并要在指尖上关闭的点等。

        祝你好运,玩得开心!

答案 1 :(得分:0)

mage dest = new Image(this.bitmap.Width,this.bitmap.Height);                    CvInvoke.cvThreshold(src,dest,220,300,Emgu.CV.CvEnum.THRESH.CV_THRESH_BINARY);                    位图nem1 =新位图(dest.Bitmap);                    this.bitmap = nem1;                    图形g = Graphics.FromImage(this.bitmap);

                using (MemStorage storage = new MemStorage()) //allocate storage for contour approximation
                    for (Contour<Point> contours = dest.FindContours(); contours != null; contours = contours.HNext)
                    {
                        g.DrawRectangle(new Pen(new SolidBrush(Color.Green)),contours.BoundingRectangle);
                       // CvInvoke.cvConvexHull2(contours,, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE, 0);
                        IntPtr seq = CvInvoke.cvConvexHull2(contours,storage.Ptr, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE, 0);
                       IntPtr defects = CvInvoke.cvConvexityDefects(contours, seq, storage);
                      Seq<Point> tr= contours.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);

                      Seq<Emgu.CV.Structure.MCvConvexityDefect> te = contours.GetConvexityDefacts(storage, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);
                      g.DrawRectangle(new Pen(new SolidBrush(Color.Green)), tr.BoundingRectangle);
                      //g.DrawRectangle(new Pen(new SolidBrush(Color.Green)), te.BoundingRectangle);

                    }

我根据你的算法做了但它不起作用 什么是拧干?

答案 2 :(得分:-1)

我认为它不会这么简单,主要是因为来自kinect的深度图像数据并不那么敏感。因此,在1米到1.5米的距离之后,所有手指都会合并,因此您无法获得清晰的轮廓来检测手指