Visión por ordenador – filtración de cascos convexos y defectos de convexidad con OpenCV
Tengo el problema con el procesamiento de señales digitales. Estoy tratando de detectar las yemas de los dedos, similar a la solución que se presenta aquí: Hand and finger detection using JavaCV .
Sin embargo, no estoy usando JavaCV, pero OpenCV para Android, que es un poco diferente. He logrado hacer todos los pasos presentados en el tutorial, pero el filtrado de cascos convexos y defectos de convexidad. Así es como se ve mi imagen:
- ¿Cómo Funciona OpenCV ORB Feature Detector?
- Muestra de detección de caras de opencv
- Edge refinamiento OpenCV android
- Convertir Vec4i a Java openCV
- Visión por computadora y bibliotecas AR disponibles para Android?
Aquí hay una imagen en otra resolución:
Como se puede ver claramente, hay muchos puntos amarillos (cascos convexos) y también a muchos puntos rojos (efectos de convexidad). A veces entre 2 puntos amarillos no hay punto rojo, que es bastante extraño (¿cómo se calculan los cascos convexos?)
Lo que necesito es crear una función de filtrado similar como en el enlace proporcionado anteriormente, pero utilizando estructuras de datos de OpenCV.
Los cascos convexos son tipo de MatOfInt … Los defectos de la convexidad son tipo de MatOfInt4 …
He creado también algunas estructuras de datos adicionales, porque estúpido OpenCV utiliza diferentes tipos de datos que contienen los mismos datos, en diferentes métodos …
convexHullMatOfInt = new MatOfInt(); convexHullPointArrayList = new ArrayList<Point>(); convexHullMatOfPoint = new MatOfPoint(); convexHullMatOfPointArrayList = new ArrayList<MatOfPoint>();
Esto es lo que hice hasta ahora, pero no está funcionando bien. El problema es probablemente con la conversión de datos en una forma incorrecta:
Creación de cascos convexos y defectos de convexidad:
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(); } }
Filtración:
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)); } }
Resultados (puntos blancos – punta de los dedos después del filtrado):
¿Podría ayudarme a escribir la función adecuada para el filtrado?
ACTUALIZACIÓN 14.08.2013
Utilizo la función openCV estándar para la aproximación de contorno. Tengo que cambiar el valor de aproximación con el cambio de resolución, y la distancia de mano a cámara, lo cual es bastante difícil de hacer. Si la resolución es menor, entonces el dedo consta de menos píxel, por lo que el valor de aproximación debe ser amante. Lo mismo con la distancia. Mantenerlo alto resultará en la pérdida completa del dedo. Así que creo que la aproximación no es un buen enfoque para resolver el problema, sin embargo pequeño valor podría ser útil para acelerar los cálculos:
Imgproc.approxPolyDP(frame, frame, 2 , true);
Si utilizo valores altos, entonces el resultado es como en la imagen de abajo, lo cual sería bueno sólo si la distancia y la resolución no cambiaran. También, estoy bastante sorprendido de que los métodos por defecto para puntos de cascos y puntos de defectos no tiene argumentos útiles para pasar (ángulo mínimo, distancia, etc) …
La imagen a continuación presenta el efecto que me gustaría lograr siempre, independientemente de la resolución o la distancia de mano a cámara. También no quiero ver ningún punto amarillo cuando cierro mi palma …
Para resumir todo, me gustaría saber:
- Cómo filtrar los puntos
- Cómo puedo hacer la resolución y la distancia independiente de la aproximación que siempre funcionará
- Si alguien sabe o tiene algunos materiales (representación gráfica, explicación) sobre las estructuras de datos utilizadas en OpenCV, estaría encantado de leerlo. (Mat, MatOfInt, MatOfPoint, MatOfPoint2, MatOfPoint4, etc.)
- Construyendo OpenCV 2.4.5 en android ADT: "ndk-build" no se encuentra en PATH
- ¿Cómo puedo detectar mejor los diferentes colores LED con la cámara de un teléfono Android y OpenCV?
- Visualización de imágenes y conversión a escala de grises - OpenCV para Android, API de Java
- Opencv aumenta la precisión del umbral
- Referencia indefinida a 'cv :: initModule_nonfree ()' En Android
- Android "No hay tal archivo o directorio" error?
- Matcher Assertions error error opencv Android
- Transformación de perspectiva
El casco convexo a baja resolución se puede utilizar para identificar la posición de la mano en su conjunto, no es útil para los dedos, sino que proporciona una región de interés y la escala adecuada.
El análisis de mayor resolución debe ser aplicado a su contorno aproximado, es fácil saltarse los puntos que no pasan los criterios de "longitud y ángulo" de los dos últimos, aunque es posible que desee "promedio en" en lugar de "omitir completamente ".
Su ejemplo de código es una sola pasada de calcular los defectos de convexidad y luego de quitarlos .. que es un error lógico .. usted necesita quitar puntos a medida que vaya .. (a) es más rápido y más sencillo de hacer todo en un paso ( B) evita eliminar puntos en un primer paso y tener que volver a agregarlos más tarde porque cualquier eliminación cambia los calcs previos.
Esta técnica básica es muy simple y así funciona para una palma abierta básica. No entiende intrínsecamente una mano o un gesto sin embargo, por lo que el ajuste de los parámetros de escala, ángulo y longitud es sólo va a llegar "hasta ahora".
Referencias a Técnicas: longitud y ángulo del filtro "Defecto de convexidad" Simen Andresen blog http://simena86.github.io/blog/2013/08/12/hand-tracking-and-recognition-with-opencv/
Kinect SDK basada en la biblioteca C # con detección de dirección de dedo añadido http://candescentnui.codeplex.com/ http://blog.candescent.ch/2011/11/improving-finger-detection.html
"Gas neuronal autoorganizado y organizado" (SGONG) Prof. Nikos Papamarkos http://www.papamarkos.gr/uploaded-files/Hand%20gesture%20recognition%20using%20a%20neural%20network%20shape%20fitting%20technique.pdf
Producto comercial David Holz y Michael Buckwald fundadores de "Leap Motion" http://www.engadget.com/2013/03/11/leap-motion-michael-buckwald-interview/
Creo que te perdiste ese punto:
La creación del casco y el análisis de defectos se aceleran utilizando una aproximación de polígono bajo del contorno en lugar del original.
- Cómo tomar fotografías con la cámara en Android mediante programación
- Desactivar LogCat Salida COMPLETAMENTE en la versión de Android app?