Procesamiento de imágenes OpenCV en el servicio de Android

Mi aplicación para Android procesa imágenes con opencv para android en una actividad con JavaCameraView . Eso funciona bien. Ahora quiero hacer el mismo procesamiento de imagen en segundo plano sin ninguna previsualización para el usuario. Comencé con un servicio de androide.

Con este código puedo cargar OpenCV con éxito en un servicio:

 import org.opencv.android.BaseLoaderCallback; import org.opencv.android.LoaderCallbackInterface; import org.opencv.android.OpenCVLoader; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class CameraService extends Service { private static final String TAG = "CameraService"; BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(CameraService.this) { @Override public void onManagerConnected(int status) { switch (status) { case LoaderCallbackInterface.SUCCESS: { Log.i("", "OpenCV loaded successfully"); } break; default: { super.onManagerConnected(status); } break; } } }; @Override public int onStartCommand(Intent intent, int flags, int startId) { if(OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_4, getApplicationContext(), mLoaderCallback)) { Log.i(TAG, "Loaded OpenCV"); } else Log.i(TAG, "Couldn't load OpenCV"); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { return null; } } 

Pero yo no sé cómo agarrar marcos como en mi actividad anterior onCameraFrame() ? Allí tengo implentent el CvCameraViewListener2 pero no en mi servicio, porque requiere un CameraBridgeViewBase que no quiero mostrar más. ¿Cómo puedo hacer el procesamiento de imágenes en un fondo como este?

ACTUALIZACIÓN -> 2

He añadido un runnable para agarrar los marcos como me lo dijiste. Loading OpenCV y conectarse a la cámara funciona bien ahora. Pero antes de agarrar cualquier marco, se salta los marcos y aborta, porque la aplicación está haciendo demasiado trabajo en el hilo principal.

Eso es todo mi servicio de cámara en este momento:

 public final class MyService extends Service { private static final String TAG = MyService.class.getSimpleName(); private boolean mStopThread; private Thread mThread; private VideoCapture mCamera; private int mCameraIndex = -1; BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { @Override public void onManagerConnected(int status) { switch (status) { case LoaderCallbackInterface.SUCCESS: { Log.i("", "OpenCV loaded successfully"); try { if (!connectCamera(640, 480)) Log.e(TAG, "Could not connect camera"); else Log.d(TAG, "Camera successfully connected"); } catch (Exception e) { Log.e(TAG, "MyServer.connectCamera throws an exception: " + e.getMessage()); } } break; default: { super.onManagerConnected(status); } break; } } }; @Override public int onStartCommand(Intent intent, int flags, int startId) { if(OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_4, getApplicationContext(), mLoaderCallback)) Log.i(TAG, "Loaded OpenCV"); else Log.i(TAG, "Couldn't load OpenCV"); return super.onStartCommand(intent, flags, startId); } public void onDestroy() { this.disconnectCamera(); Log.d(TAG, "onDestroy"); super.onDestroy(); } private boolean connectCamera(int width, int height) { /* First step - initialize camera connection */ if (!initializeCamera(width, height)) { Log.d(TAG, "initializeCamera failed"); return false; } else { Log.d(TAG, "initializeCamera successfully"); /* start update thread */ mThread = new Thread(new CameraWorker()); mThread.start(); return true; } } private boolean initializeCamera(int width, int height) { synchronized (this) { if (mCameraIndex == -1) mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID); else mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID + mCameraIndex); if (mCamera == null) return false; if (mCamera.isOpened() == false) return false; /* Select the size that fits surface considering maximum size allowed */ Size frameSize = new Size(width, height); mCamera.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, frameSize.width); mCamera.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, frameSize.height); } return true; } private void releaseCamera() { synchronized (this) { if (mCamera != null) { mCamera.release(); } } } private void disconnectCamera() { // 1. Stop thread which updating the frames // 2. Stop camera and release it try { mStopThread = true; mThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } finally { mThread = null; mStopThread = false; } releaseCamera(); } private class CameraWorker implements Runnable { public void run() { do { if (!mCamera.grab()) { Log.e(TAG, "Camera frame grab failed"); break; } Log.e(TAG, "Camera frame grabbed"); // img processing } while (!mStopThread); } } @Override public IBinder onBind(Intent intent) { return null; // Not used } } 

Mi registro:

 11-29 12:28:24.370: D/OpenCVManager/Helper(5257): Init finished with status 0 11-29 12:28:24.370: D/OpenCVManager/Helper(5257): Unbind from service 11-29 12:28:24.380: D/OpenCVManager/Helper(5257): Calling using callback 11-29 12:28:24.380: I/(5257): OpenCV loaded successfully 11-29 12:28:24.380: D/OpenCV::camera(5257): CvCapture_Android::CvCapture_Android(0) 11-29 12:28:24.440: D/OpenCV_NativeCamera(5257): Connecting to CameraService v 3D 11-29 12:28:24.670: D/OpenCV_NativeCamera(5257): Instantiated new CameraHandler (0x75e4f29d, 0x71e178b8) 11-29 12:28:24.750: D/OpenCV_NativeCamera(5257): Starting preview 11-29 12:28:25.421: E/OpenCV_NativeCamera(5257): CameraHandler::doCall(void*, size_t): cameraCallback returns false (camera connection will be closed) 11-29 12:28:25.421: E/BufferQueue(5257): [unnamed-5257-0] dequeueBuffer: min undequeued buffer count (2) exceeded (dequeued=11 undequeudCount=0) 11-29 12:28:25.431: E/BufferQueue(5257): [unnamed-5257-0] dequeueBuffer: min undequeued buffer count (2) exceeded (dequeued=10 undequeudCount=1) 11-29 12:28:25.451: D/OpenCV_NativeCamera(5257): Preview started successfully 11-29 12:28:25.451: D/OpenCV_NativeCamera(5257): CameraHandler::setProperty(0, 640.000000) 11-29 12:28:25.451: D/OpenCV_NativeCamera(5257): CameraHandler::setProperty(1, 480.000000) 11-29 12:28:25.451: D/MyService(5257): initializeCamera successfully 11-29 12:28:25.451: D/MyService(5257): Camera successfully connected 11-29 12:28:25.451: I/Choreographer(5257): Skipped 86 frames! The application may be doing too much work on its main thread. 11-29 12:28:25.471: A/libc(5257): @@@ ABORTING: LIBC: HEAP MEMORY CORRUPTION IN tmalloc_small 11-29 12:28:25.471: A/libc(5257): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 5257 () 

¿Qué está mal y qué puedo hacer ahora?

Puede utilizar la variante nativa ( VideoCapture ). CameraBridgeViewBase – se extiende desde Android.Camera y también dont't trabajo en segundo plano. Si no encuentra ejemplo, en OpenCv-2.4.2 biblioteca de Android ver ejemplo FaceDetection

UPD:

Puede obtener fotogramas de la cámara, utilizando Intefrace Runnable:

 private VideoCapture mCamera; public void run() { Log.i(TAG, "Starting processing thread"); while (true) { Bitmap bmp = null; synchronized (this) { if (mCamera == null) break; if (!mCamera.grab()) { Log.e(TAG, "mCamera.grab() failed"); break; } bmp = processFrame(mCamera); } 

}

  • Eclipse - Método NewStringUTF () no se pudo resolver
  • OpenCV para Android - NativeCameraView todavía existe?
  • Cómo obtener GNU C en las preferencias
  • Codificación de video Android con fr y manipulación de resolución
  • Comparación de imágenes de OpenCV en Android
  • OpenCV Android NDK Project no creará
  • (OpenCV) no puede encontrar Core.line en Android Studio
  • Android OpenCV con MatOfKeyPoint y detección de feature2d
  • Detección de elipse con OpenCV
  • Pasar una matriz de Mats a código nativo
  • NDK ¿La manipulación del mapa de bits usando el color azul de OpenCv es anaranjada?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.