OpenCV Android Вычитание фона - PullRequest
       41

OpenCV Android Вычитание фона

8 голосов
/ 12 февраля 2012

Я работаю над робототехническим проектом с использованием телефона Android в качестве основного процессора и камеры для обнаружения движения.Я получил двоичный пакет Android от OpenCV и правильно установил его.Я могу захватывать изображения с помощью встроенной камеры OpenCV и отображать их на экране.У меня проблемы с использованием фона вычитания фона, хотя.Я могу создать новый объект BackgroundSubtractorMOG в конструкторе, но когда я пытаюсь запустить приведенный ниже код, он принудительно завершает работу, и я получаю сообщение об ошибке «Только 1- и 3-канальные 8-битные изображения поддерживаются в BackgroundSubtractorMOG» из собственного кода.Я попытался изменить Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA на Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGB, и затем он не принудительно завершается, но все, что я получаю, это черный экран.Я почти уверен, что bmp все еще равен нулю с FRAME_RGB, потому что экран остается черным, а счетчик fps, который я рисовал сразу после растрового изображения (удален из кода, приведенного ниже для ясности и как этап устранения неполадок), не отображается.

Я взглянул на код OpenCV C ++ для этой функции ( строка 388 здесь ), и возникает ошибка типа изображения, если тип изображения не CV_8UC1 или CV_8UC3, поэтому я попыталсяиспользование java CvType.CV_8UC3 вместо Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA в capture.retrieve (), но оно принудительно закрылось, и я получил ошибку «Формат кадра вывода не поддерживается».

Я предполагаю, что я только чтоУ меня возникла проблема с преобразованием типов, но я не могу понять, где именно типы изображений OpenCV для Android соответствуют их обычным типам изображений, которые задокументированы.Любая помощь приветствуется.

Переменные:

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

Функция run () моего 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();
    }
}

Функция processFrame (), на которую ссылается run ():

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

Редактировать:

Решение, которое заработало:

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

Ответы [ 3 ]

4 голосов
/ 12 февраля 2012

Вы пытались использовать cvtColor с CV_RGB2RGBA и CV_RGBA2RGB. Поэтому, возможно, попробуйте преобразовать кадр RGBA в RGB, а затем выполните вычитание фона. Как то так:

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: Вы можете проверить модульный тест OpenCV для BackgroundSubtractorMOG, расположенного здесь . Тем не менее, тест имеет fail("Not yet implemented"); в основном тестовом случае.

Я не уверен, означает ли это, что тест не завершен или поддержка BackgroundSubtractorMOG не реализована. Вы можете попробовать запустить код, содержащийся в этом модульном тесте, чтобы проверить, действительно ли он работает.

Кроме того, пример C ++ сегмент_объектов.cpp может быть полезен в качестве примера использования.

Надеюсь, это поможет! :)

2 голосов
/ 05 марта 2013

Спасибо вам, ребята!А для будущих зрителей, которые придут на эту страницу, вам, возможно, придется настроить эти знания, чтобы все заработало.В SDK v2.4.4 я применил это в методе onCameraFrame.Напомним, что метод принимает входной кадр с камеры.Вы используете вход и возвращаете кадр, который должен отображаться на экране вашего устройства Android.Вот пример:

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

Чтобы понять мою мысль о сером изображении, которое выходит из apply (), если вы хотите создать версию RGBA, вам может потребоваться использовать цвет cvtcolor после вызова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;
}
0 голосов
/ 10 февраля 2016

Также с последним openCV вам нужно инициализировать с помощью:

приватный BackgroundSubtractorMOG2 Sub = Video.createBackgroundSubtractorMOG2 ();

...