Substracción de fondo de OpenCV Android

Estoy trabajando en un proyecto de robótica utilizando un teléfono Android como el procesador principal y la cámara para detectar el movimiento. Tengo el paquete binario de Android de OpenCV y lo tengo instalado correctamente. Puedo capturar imágenes usando la cámara nativa de OpenCV y mostrarlas a la pantalla. Tengo problemas al usar la clase de resta de fondo, sin embargo. Puedo hacer un nuevo objeto de BackgroundSubtractorMOG en el constructor, pero cuando intento ejecutar el código abajo, fuerza los interruptos consigo el error "solamente las imágenes de 8 y 8 bits de 1 y 3 canales son soportadas en BackgroundSubtractorMOG" del código nativo. Intenté cambiar Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA a Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGB, y luego no obliga a salir, pero todo lo que consigo es una pantalla en negro. Estoy bastante seguro de bmp sigue siendo nulo con FRAME_RGB, porque la pantalla permanece en negro, y el contador fps estaba dibujo justo después de que el mapa de bits (eliminado del código publicado a continuación para mayor claridad y como un paso de solución de problemas) no aparece.

He echado un vistazo al código OpenCV C ++ para esta función ( línea 388 aquí ), y el error de tipo de imagen se produce si el tipo de imagen no es CV_8UC1 o CV_8UC3, así que he intentado usar el java CvType.CV_8UC3 en lugar de Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA in Capture.retrieve (), pero la fuerza cerrada y tengo un "Formato de salida de formato no es compatible" error.

Supongo que sólo tengo un problema de conversión de tipo, pero no puedo imaginar la vida de mí donde los tipos de imágenes específicas de Android de OpenCV encajan con sus tipos de imagen regulares que están documentados. Cualquier ayuda sería apreciada.

Las variables:

private SurfaceHolder mHolder; private VideoCapture mCamera; private Mat mRgba; private Mat mFGMask; private BackgroundSubtractorMOG mBGSub; 

La función run () de mi SurfaceView:

 public void run() { Bitmap bmp = null; synchronized (this) { if (mCamera == null) break; if (!mCamera.grab()) { Log.e(TAG, "mCamera.grab() failed"); break; } processFrame(mCamera); bmp = Bitmap.createBitmap(mFGMask.cols(), mFGMask.rows(), Bitmap.Config.ARGB_8888); Utils.matToBitmap(mFGMask, bmp); } if (bmp != null) { Canvas canvas = mHolder.lockCanvas(); if (canvas != null) { canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth()) / 2, (canvas.getHeight() - bmp.getHeight()) / 2, null); mHolder.unlockCanvasAndPost(canvas); } bmp.recycle(); } } 

La función processFrame () se hace referencia en run ():

 protected void processFrame(VideoCapture capture) { capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA); mBGSub.apply(mRgba, mFGMask); } 

Editar:

La solución que terminó funcionando:

 protected void processFrame(VideoCapture capture) { capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGB); //GREY_FRAME also works and exhibits better performance //capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_GREY_FRAME); mBGSub.apply(mRgba, mFGMask, 0.1); Imgproc.cvtColor(mFGMask, mRgba, Imgproc.COLOR_GRAY2BGRA, 4); } 

¿Ha intentado usar cvtColor con CV_RGB2RGBA y CV_RGBA2RGB . Por lo tanto, tal vez tratar de convertir el marco RGBA a RGB, a continuación, hacer substracción de fondo. Algo como esto:

 protected void processFrame(VideoCapture capture) { capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA); Mat rgb; Imgproc.cvtColor(mRgba, rgb, Imgproc.COLOR_RGBA2RGB); mBGSub.apply(rgb, mFGMask); } 

EDIT: Puede comprobar la prueba de unidad OpenCV para BackgroundSubtractorMOG encuentra aquí . Sin embargo, la prueba ha fail("Not yet implemented"); En el caso de prueba principal.

No estoy seguro de si eso significa que la prueba no está completa, o el soporte para BackgroundSubtractorMOG no está implementado. Puede intentar ejecutar el código contenido en esta prueba de unidad para ver si realmente funciona.

Además, la muestra de C ++ segment_objects.cpp podría ser útil como ejemplo de uso.

¡Espero que ayude! 🙂

¡Muchísimas gracias! Y para los futuros espectadores que vienen a esta página, es posible que tenga que ajustar este conocimiento para que las cosas funcionen. En SDK v2.4.4 lo apliqué en el método onCameraFrame. Recuerde que el método toma un marco de entrada de la cámara. Utiliza la entrada y devuelve el marco que se va a mostrar en la pantalla de tu dispositivo android. He aquí un ejemplo:

 //Assume appropriate imports private BackgroundSubtractorMOG sub = new BackgroundSubtractorMOG(3, 4, 0.8); private Mat mGray = new Mat(); private Mat mRgb = new Mat(); private Mat mFGMask = new Mat(); public Mat onCameraFrame(CvCameraViewFrame inputFrame) { mGray = inputFrame.gray(); //I chose the gray frame because it should require less resources to process Imgproc.cvtColor(mGray, mRgb, Imgproc.COLOR_GRAY2RGB); //the apply function will throw the above error if you don't feed it an RGB image sub.apply(mRgb, mFGMask, learningRate); //apply() exports a gray image by definition return mFGMask; } 

Para obtener mi punto acerca de la imagen gris que sale de apply (), si desea hacer una versión RGBA, puede que tenga que utilizar un cvtcolor después de la llamada a apply ():

 private Mat mRgba = new Mat(); public Mat onCameraFrame(CvCameraViewFrame inputFrame) { mRgba = inputFrame.rgba(); Imgproc.cvtColor(mRgba, mRgb, Imgproc.COLOR_RGBA2RGB); //the apply function will throw the above error if you don't feed it an RGB image sub.apply(mRgb, mFGMask, learningRate); //apply() exports a gray image by definition Imgproc.cvtColor(mFGMask, mRgba, Imgproc.COLOR_GRAY2RGBA); return mRgba; } 

También con la última openCV que necesita para inicializar con:

Private BackgroundSubtractorMOG2 Sub = Video.createBackgroundSubtractorMOG2 ();

  • OpenCV instalador independiente opencv
  • Reconocimiento de imágenes con SURF con OpenCV en Android
  • Error OpenCV: No se puede cargar la biblioteca de información para OpenCV
  • Programaticamente encuentre imágenes trémulas o fuera de foco
  • Comparar imágenes SIFT / SURF detalles en archivos .yml OpenCV?
  • Buscando OpenCV android tutorial
  • Errores de compilación de OpenCV / Android
  • Conversión de OpenCV C ++ a Java para problemas de detección de formas
  • Reconocimiento y seguimiento de objetos en movimiento más rápido en Android
  • Cómo calcular la diferencia entre 2 fotogramas entrantes de la cámara (CV abierto)
  • La cámara no está abierta - Inicialización estática en OpenCV Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.