デジタル信号の処理に問題があります。ここに示されているソリューションと同様に、指先を検出しようとしています: JavaCV を使用した手と指の検出。
ただし、私はJavaCVを使用していませんが、Android用のOpenCVは少し異なります。チュートリアルに示されているすべての手順を実行できましたが、凸包と凸欠陥のフィルタリングが必要です。これは私のイメージがどのように見えるかです:
別の解像度の画像を次に示します。
はっきりとわかるように、多くの黄色い点 (凸包) と多くの赤い点 (凸効果) があります。ときどき 2 つの黄色の点の間に赤い点がないことがありますが、これは非常に奇妙です (凸包はどのように計算されますか?)
私が必要とするのは、以前に提供されたリンクのような同様のフィルタリング機能を作成することですが、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);
高い値を使用すると、結果は下の画像のようになります。これは、距離と解像度が変わらない場合にのみ有効です。また、船体ポイントと欠陥ポイントのデフォルトのメソッドには、渡すのに役立つ引数(最小角度、距離など)がないことに非常に驚いています...
下の画像は、解像度や手とカメラの距離に関係なく、常に実現したい効果を表しています。また、手のひらを閉じたときに黄色い点が表示されたくない...
すべてを要約すると、私は知りたいです:
- ポイントをフィルタリングする方法
- 常に機能する解像度と距離に依存しない近似を作成するにはどうすればよいですか
- OpenCV で使用されているデータ構造について誰かが知っているか、何らかの資料 (グラフィック表現、説明) を持っている場合は、喜んでそれを読んでください。(Mat、MatOfInt、MatOfPoint、MatOfPoint2、MatOfPoint4 など)