我在处理数字信号时遇到问题。我正在尝试检测指尖,类似于此处提供的解决方案:Hand and finger detection using JavaCV。
但是,我使用的不是JavaCV,而是Android的OpenCV,它略有不同。
我设法完成了本教程中介绍的所有步骤,但是过滤了凸包和凸缺陷。这是我的图像的样子:
这是另一种分辨率的图像:
您可以清楚地看到,有很多黄色的点(凸包)和很多红色的点(凸缺陷)。有时在两个黄色点之间没有红色点,这很奇怪(如何计算凸包?)
我需要像在前面提供的链接中那样创建类似过滤功能,但是要使用OpenCV的数据结构。
凸包是MatOfInt的类型...
凸性缺陷是MatOfInt4的类型...
我还创建了一些其他数据结构,因为愚蠢的OpenCV在不同的方法中使用了包含相同数据的不同类型的数据。
convexHullMatOfInt = new MatOfInt();
convexHullPointArrayList = new ArrayList<Point>();
convexHullMatOfPoint = new MatOfPoint();
convexHullMatOfPointArrayList = new ArrayList<MatOfPoint>();
这是我到目前为止所做的,但效果不佳。问题可能出在以错误的方式转换数据:
创建凸包和凸缺陷:
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();
}
}
过滤条件:
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函数进行轮廓逼近。我必须随着分辨率的变化以及到相机的距离更改近似值,这很难做到。如果分辨率较小,则手指包含的像素较少,因此近似值应该是爱人。与距离相同。保持高电平会导致完全失去手指。因此,我认为近似值并不是解决问题的好方法,但是较小的值可能有助于加快计算速度:
Imgproc.approxPolyDP(frame, frame, 2 , true);
如果我使用高值,则结果如下面的图片所示,仅在距离和分辨率不变的情况下才是好的。 另外,令我惊讶的是,用于船体点和缺陷点的默认方法没有有用的参数可以传递(最小角度,距离等)...
下图显示了我希望始终获得的效果,而与分辨率或手到相机的距离无关。另外,当我合上手掌时,我也不想看到任何黄点...
总结一下,我想知道:
最佳答案
低分辨率的凸包可用于识别整个手的位置,它对手指没有用,但确实提供了感兴趣的区域和适当的比例。
然后应将较高分辨率的分析应用于您的近似轮廓,尽管您可能希望“取平均值”而不是“完全跳过”,但很容易从最后两个点跳过任何未通过“长度和角度”标准的点。 ”。
您的代码示例是计算凸度缺陷然后消除它们的单步操作..这是一种逻辑错误..您需要在移动过程中移除点..(a)单步执行所有操作会更快,更简单( b)它避免了在第一次通过时删除点,而不必在以后再添加它们,因为任何删除都会改变以前的计算结果。
此基本技术非常简单,因此适用于基本的开放手掌。但是,它本质上并不能理解手或手势,因此调整比例,角度和长度参数只会使您“走到现在”。
技术引用:
过滤器的长度和角度“凸度缺陷”
Simen Andresen博客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 Holz和Michael Buckwald创建了“Leap Motion” http://www.engadget.com/2013/03/11/leap-motion-michael-buckwald-interview/
关于java - 计算机视觉-使用OpenCV过滤凸包和凸缺陷,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18143077/