首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于OpenCV的计算机视觉滤波凸壳与凸性缺陷

基于OpenCV的计算机视觉滤波凸壳与凸性缺陷
EN

Stack Overflow用户
提问于 2013-08-09 08:45:21
回答 2查看 12.7K关注 0票数 46

我在处理数字信号方面有问题。我正在尝试检测指尖,类似于这里提出的解决方案:基于JavaCV的手指头检测

然而,我使用的不是JavaCV,而是OpenCV,这与安卓略有不同。我已经完成了本教程中介绍的所有步骤,但是过滤了凸壳和凸性缺陷。我的形象是这样的:

下面是另一种分辨率中的图像:

你可以清楚地看到,有许多黄色点(凸壳),也有许多红点(凸性差)。有时在两个黄点之间没有红点,这是相当奇怪的(如何计算凸壳?)

我需要的是像前面提供的链接一样创建simillar过滤函数,但是使用OpenCV的数据结构。

凸壳是MatOfInt .凸性缺陷是MatOfInt4的一种.

我还创建了一些额外的数据结构,因为愚蠢的OpenCV在不同的方法中使用不同类型的包含相同数据的数据.

代码语言:javascript
复制
convexHullMatOfInt = new MatOfInt();
convexHullPointArrayList = new ArrayList<Point>();
convexHullMatOfPoint = new MatOfPoint();
convexHullMatOfPointArrayList = new ArrayList<MatOfPoint>();

这是我到目前为止所做的事情,但效果并不好。问题可能在于以错误的方式转换数据:

制造凸壳和凸性缺陷:

代码语言:javascript
复制
public void calculateConvexHulls()
{
    convexHullMatOfInt = new MatOfInt();
    convexHullPointArrayList = new ArrayList<Point>();
    convexHullMatOfPoint = new MatOfPoint();
    convexHullMatOfPointArrayList = new ArrayList<MatOfPoint>();

    try {
        //Calculate convex hulls
        if(aproximatedContours.size() > 0)
        {
            Imgproc.convexHull( aproximatedContours.get(0), convexHullMatOfInt, false);

            for(int j=0; j < convexHullMatOfInt.toList().size(); j++)
                convexHullPointArrayList.add(aproximatedContours.get(0).toList().get(convexHullMatOfInt.toList().get(j)));
            convexHullMatOfPoint.fromList(convexHullPointArrayList);
            convexHullMatOfPointArrayList.add(convexHullMatOfPoint);    
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        Log.e("Calculate convex hulls failed.", "Details below");
        e.printStackTrace();
    }
}

public void calculateConvexityDefects()
{
    mConvexityDefectsMatOfInt4 = new MatOfInt4();

    try {
        Imgproc.convexityDefects(aproximatedContours.get(0), convexHullMatOfInt, mConvexityDefectsMatOfInt4);

        if(!mConvexityDefectsMatOfInt4.empty())
        {
            mConvexityDefectsIntArrayList = new int[mConvexityDefectsMatOfInt4.toArray().length];
            mConvexityDefectsIntArrayList = mConvexityDefectsMatOfInt4.toArray();
        }
    } catch (Exception e) {
        Log.e("Calculate convex hulls failed.", "Details below");
        e.printStackTrace();
    }
}

过滤:

代码语言:javascript
复制
public void filterCalculatedPoints()
    {
        ArrayList<Point> tipPts = new ArrayList<Point>();
        ArrayList<Point> foldPts = new ArrayList<Point>();
        ArrayList<Integer> depths = new ArrayList<Integer>();

        fingerTips = new ArrayList<Point>();

        for (int i = 0; i < mConvexityDefectsIntArrayList.length/4; i++)
        {
            tipPts.add(contours.get(0).toList().get(mConvexityDefectsIntArrayList[4*i]));
            tipPts.add(contours.get(0).toList().get(mConvexityDefectsIntArrayList[4*i+1]));
            foldPts.add(contours.get(0).toList().get(mConvexityDefectsIntArrayList[4*i+2]));
            depths.add(mConvexityDefectsIntArrayList[4*i+3]);
        }

        int numPoints = foldPts.size();
        for (int i=0; i < numPoints; i++) {
            if ((depths.get(i).intValue()) < MIN_FINGER_DEPTH)
                continue;

            // look at fold points on either side of a tip
            int pdx = (i == 0) ? (numPoints-1) : (i - 1);
            int sdx = (i == numPoints-1) ? 0 : (i + 1);

            int angle = angleBetween(tipPts.get(i), foldPts.get(pdx), foldPts.get(sdx));
            if (angle >= MAX_FINGER_ANGLE)   // angle between finger and folds too wide
                continue; 

            // this point is probably a fingertip, so add to list
            fingerTips.add(tipPts.get(i));
        }
    }

结果(白点-过滤后的指尖):

你能帮我写个适当的过滤函数吗?

更新14.08.2013

我使用标准的openCV函数进行等高线近似。我必须改变分辨率变化的近似值,和手对相机的距离,这是相当困难的。如果分辨率较小,则手指由较少的像素组成,因此近似值应该是情人。距离也一样。保持它高将导致完全失去手指。因此,我认为近似并不是解决问题的好办法,尽管小数值可能有助于加速计算:

代码语言:javascript
复制
Imgproc.approxPolyDP(frame, frame, 2 , true); 

如果我使用高值,那么结果就像在下面的图像,这将是好的,只有当距离和分辨率不会改变。也很惊讶,对于船体点和缺陷点的默认方法没有有用的参数可通过(最小角度、距离等).

下面的图片显示了我想要达到的效果,独立于分辨率或手对相机的距离。当我闭上手掌时,我也不想看到任何黄点.

总之,我想知道:

  • 如何滤除点
  • 如何使分辨率和距离独立的近似总是工作的。
  • 如果有人知道或有一些关于OpenCV中使用的数据结构的材料(图形表示,解释),我很乐意阅读它。(Mat,MatOfInt,MatOfPoint,MatOfPoint2,MatOfPoint4等)

EN

回答 2

Stack Overflow用户

发布于 2013-10-12 20:28:08

在低分辨率的凸包可以用来识别整个手的位置,它对手指没有用处,但确实提供了感兴趣的区域和适当的尺度。

高分辨率的分析应该应用于你的近似轮廓,很容易跳过任何不符合“长度和角度”标准的点,尽管你可能希望“平均”而不是“完全跳过”。

您的代码示例是计算凸性缺陷然后删除它们的一次传递。这是一个逻辑错误。当你走的时候你需要移除点。(a)在一次传递中完成所有操作更快、更简单(b)它避免在第一次传递时删除点数,并在以后添加它们,因为任何删除都会改变以前的计算。

这一基本技术非常简单,因此适用于基本的开放手掌。然而,它在本质上并不理解一只手或一种手势,因此调整尺度、角度和长度参数只会让你“到目前为止”。

参考技术:过滤长度和角度“凸性缺陷”Simen博客http://simena86.github.io/blog/2013/08/12/hand-tracking-and-recognition-with-opencv/

基于Kinect SDK的C#库添加手指方向检测http://candescentnui.codeplex.com/ http://blog.candescent.ch/2011/11/improving-finger-detection.html

“自生长和有组织的神经气体”(SGONG)尼科斯帕帕马科斯教授( Nikos Papamarkos http://www.papamarkos.gr/uploaded-files/Hand%20gesture%20recognition%20using%20a%20neural%20network%20shape%20fitting%20technique.pdf )

商业产品David & Michael是"Leap Motion“http://www.engadget.com/2013/03/11/leap-motion-michael-buckwald-interview/的创始人

票数 1
EN

Stack Overflow用户

发布于 2013-08-13 12:16:29

我想你错过了这一点:

利用等高线的低多边形近似来加速船体的生成和缺陷分析。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18143077

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档