我在处理数字信号时遇到问题。我正在尝试检测手指,类似于这里提供的解决方案:使用JavaCV进行手部和手指检测 。但是,我没有使用JavaCV而是使用了略有不同的OpenCV for android。我已经完成了教程中介绍的所有步骤,但无法过滤凸包和凸性缺陷。这是我的图像外观:
此处省略图片
正如您可以清楚地看到的那样,有太多的黄色点(凸包)和红色点(凸性缺陷)。有时在两个黄点之间没有红点,这相当奇怪(凸包是如何计算的?)我需要创建类似于链接提供的过滤函数,但要使用OpenCV的数据结构。
凸包是MatOfInt类型... 凸性缺陷是MatOfInt4类型...
我还创建了一些附加数据结构,因为愚蠢的OpenCV在不同的方法中使用包含相同数据的不同类型的数据...
如果我使用高值,则结果如下图所示,只有当距离和分辨率不变时才会很好。 此外,我相当惊讶默认的凸壳点和缺陷点方法没有有用的参数可传递(最小角度,距离等)... 下面的图像展示了我希望始终实现的效果,独立于分辨率或手到相机的距离。而且,当我握紧拳头时,我不想看到任何黄色点...
总之,我想知道:
- 如何过滤这些点 - 如何进行分辨率和距离无关的逼近,以便始终有效 - 如果有人知道或有一些关于OpenCV中使用的这些数据结构(Mat、MatOfInt、MatOfPoint、MatOfPoint2、MatOfPoint4等)的材料(图形表示、说明),我将很高兴阅读它。
此处省略图片
正如您可以清楚地看到的那样,有太多的黄色点(凸包)和红色点(凸性缺陷)。有时在两个黄点之间没有红点,这相当奇怪(凸包是如何计算的?)我需要创建类似于链接提供的过滤函数,但要使用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));
}
}
结果(白点-经过筛选后的指尖):
你能帮我编写适当的筛选函数吗?
更新于2013年8月14日
我使用标准的openCV函数进行轮廓近似。我必须根据分辨率变化和手到摄像头的距离来改变近似值,这非常困难。如果分辨率较小,则手指由更少的像素组成,因此近似值应该更低。同样,距离也是如此。保持高度将导致完全失去手指。因此,我认为近似并不是解决问题的好方法,但小的值可能有助于加快计算速度:
Imgproc.approxPolyDP(frame, frame, 2 , true);
如果我使用高值,则结果如下图所示,只有当距离和分辨率不变时才会很好。 此外,我相当惊讶默认的凸壳点和缺陷点方法没有有用的参数可传递(最小角度,距离等)... 下面的图像展示了我希望始终实现的效果,独立于分辨率或手到相机的距离。而且,当我握紧拳头时,我不想看到任何黄色点...
总之,我想知道:
- 如何过滤这些点 - 如何进行分辨率和距离无关的逼近,以便始终有效 - 如果有人知道或有一些关于OpenCV中使用的这些数据结构(Mat、MatOfInt、MatOfPoint、MatOfPoint2、MatOfPoint4等)的材料(图形表示、说明),我将很高兴阅读它。
![enter image description here](https://istack.dev59.com/ZBjdh.webp)