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:

Resolución 640x480

Aquí hay una imagen en otra resolución:

Resolución 320x240

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):

Introduzca aquí la descripción de la imagen

¿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.)

Introduzca aquí la descripción de la imagen

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.

  • No se puede obtener el warpPerspective de OpenCV para trabajar en Android
  • Cómo poner el marcador estable (círculo sólido en la imagen). ¿Cuál estará en la misma posición en el próximo marco de la cámara?
  • Android Detección de la cara con OpenCV / JavaCV
  • Uso de la cámara LED Flash con OpenCV en Android
  • Opencv C + + crear objeto Mat de android NV21 buffer de datos de imagen
  • Filtrado de MatOfDMatch
  • Cómo detectar la pupila del ojo circularmente en opencv
  • Problema de orientación de la cámara OpenCV
  • Cómo detectar los límites de una página de pasaporte con OpenCV?
  • Adición de archivos .so a jniLibs en Android Studio: archivos duplicados durante el envasado de APK
  • Decodificación de flujo de vídeo en Android de DJI drone
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.