簡體   English   中英

Android服務中的OpenCV圖像處理

[英]OpenCV image processing in Android service

我的android應用在帶有JavaCameraView的活動中使用opencv for android進行圖像處理。 很好 現在,我想在后台進行相同的圖像處理,而無需為用戶提供任何預覽。 我開始使用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的CvCameraViewListener2但是在我的服務中卻沒有,因為它需要一個我不想再顯示的CameraBridgeViewBase 如何在這樣的背景下進行圖像處理?

更新-> 2

我添加了一個runnable來抓取您告訴我的幀。 現在加載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 ()

怎么了,我現在該怎么辦?

您可以使用本機變體( VideoCapture )。 CameraBridgeViewBase-從Android.Camera擴展而來,在后台也不起作用。 如果找不到示例,請在OpenCv-2.4.2 Android庫中查看示例FaceDetection

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

        }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM