2013-11-28 12 views
7

私のAndroidアプリケーションは、JavaCameraViewのアクティビティでアンドロイド用のopencvで画像処理を行います。 これは問題なく動作します。今私はユーザーのためのプレビューなしでバックグラウンドで同じ画像処理をしたい。私はアンドロイドサービスから始めました。私はサービスで成功しOpenCVのを読み込むことができます。このコードでAndroidサービスのOpenCV画像処理

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; 
} 

} 

しかし、私は私のかつての活動onCameraFrame()のようにフレームをつかむ方法がわかりませんか? 私は黙示的にCvCameraViewListener2を持っていますが、それは私がもう表示したくないCameraBridgeViewBaseを必要としているため、私のサービスではありません。 このような背景で画像処理を行うにはどうすればよいですか?

UPDATE - > 2

私はあなたが私に言ったように、フレームをつかむために実行可能を追加しました。 OpenCVを読み込んでカメラに接続しても問題ありません。しかし、フレームを取得する前に、フレームをスキップして終了します。これは、アプリケーションがメインスレッドであまりにも多くの作業をしているためです。

は今、私のカメラ全体のサービスを厥:

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 
} 
} 

マイログ:

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

いただきました間違ったと私は今何ができるのでしょうか?

+0

エラーログ:11-28 13:19:04.095:E/OpenCV :: camera(2931):|| libnative_camera_r2.3.3.soですが、動作しています。このエントリを無視してください – user1755546

+0

その後:D/OpenCV_NativeCamera(2931):CameraServiceに接続する。v 3D、何も起こらない。アプリはforzenです。 – roschulze

+0

これはネイティブの例です。どのようにカメラからフレームを取得しますか? – user1755546

答えて

2

ネイティブバリアント(VideoCapture)を使用できます。 CameraBridgeViewBase - Android.Cameraから拡張され、バックグラウンドでも動作しません。あなたは例が見つからない場合は、OpenCVの-2.4.2のAndroidライブラリに例顔検出

UPD参照:

をあなたは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); 

     } 

}