Je sais que cette question peut être un peu longue et difficile, mais s'il vous plaît, prenez votre temps pour m'aider, ou au moins votez en haut pour que quelqu'un d'autre, qui connaît bien le sujet, soit en mesure d'aider parce que la question apparaîtra en haut... (c'est vraiment important pour moi et la date limite pour terminer est la semaine prochaine). Merci dans la mendicité.
J'ai un problème de traitement des signaux numériques. J'essaye de détecter le bout des doigts, de manière similaire à la solution qui est présentée ici : Détection des mains et des doigts à l'aide de JavaCV .
Cependant, je n'utilise pas JavaCV mais OpenCV pour Android qui est légèrement différent. J'ai réussi à faire toutes les étapes présentées dans le tutoriel, mais le filtrage des coques convexes et des défauts de convexité. Voici à quoi ressemble mon image :
Voici une image dans une autre résolution :
Comme vous pouvez le voir, il y a trop de points jaunes (coques convexes) et trop de points rouges (effets de convexité). Parfois, entre deux points jaunes, il n'y a pas de point rouge, ce qui est assez étrange (comment sont calculées les coques convexes ?).
Ce dont j'ai besoin est de créer une fonction de filtrage similaire à celle du lien fourni précédemment, mais en utilisant les structures de données d'OpenCV.
Les coques convexes sont de type MatOfInt ... Les défauts de convexité sont de type MatOfInt4 ...
J'ai aussi créé quelques structures de données supplémentaires, parce que stupidement OpenCV utilise différents types de données contenant les mêmes données, dans différentes méthodes...
convexHullMatOfInt = new MatOfInt();
convexHullPointArrayList = new ArrayList<Point>();
convexHullMatOfPoint = new MatOfPoint();
convexHullMatOfPointArrayList = new ArrayList<MatOfPoint>();
Voici ce que j'ai fait jusqu'à présent mais cela ne fonctionne pas bien. Le problème est probablement dû à une mauvaise conversion des données :
Création de coques convexes et de défauts de convexité :
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();
}
}
Filtrage :
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));
}
}
Résultats (points blancs - bouts des doigts après filtrage) :
Pouvez-vous m'aider à écrire une fonction appropriée pour le filtrage ?
MISE À JOUR 14.08.2013
J'utilise une fonction openCV standard pour l'approximation des contours. Je dois changer la valeur de l'approximation en fonction de la résolution et de la distance entre la main et la caméra, ce qui est assez difficile à faire. Si la résolution est plus petite, alors le doigt est composé de moins de pixels, donc la valeur d'approximation devrait être plus petite. De même pour la distance. Si on la garde élevée, on perd complètement le doigt. Je pense donc que l'approximation n'est pas une bonne approche pour résoudre le problème, mais une petite valeur pourrait être utile pour accélérer les calculs :
Imgproc.approxPolyDP(frame, frame, 2 , true);
Si j'utilise des valeurs élevées, alors le résultat est comme sur l'image ci-dessous, ce qui serait bon seulement si la distance et la résolution ne changeaient pas. De plus, je suis assez surpris que les méthodes par défaut pour les points de coques et les points de défauts n'aient pas d'arguments utiles à passer (angle min, distance etc.)...
L'image ci-dessous présente l'effet que j'aimerais obtenir en permanence, indépendamment de la résolution ou de la distance main-caméra. Je ne veux pas non plus voir de points jaunes lorsque je ferme ma paume...
Pour résumer le tout, j'aimerais savoir :
- comment filtrer les points
- comment puis-je faire une approximation indépendante de la résolution et de la distance qui fonctionnera toujours ?
- Si quelqu'un connaît ou a du matériel (représentation graphique, explication) sur ces structures de données utilisées dans OpenCV, je serais heureux de le lire. (Mat, MatOfInt, MatOfPoint, MatOfPoint2, MatOfPoint4 etc.)