OpenCV Android Вычитание Фона
Я работаю над робототехническим проектом, используя телефон Android в качестве основного процессора и камеры для обнаружения движения. Я получил бинарный пакет Android от OpenCV и правильно установил его. Я могу снимать изображения с помощью встроенной камеры OpenCV и выводить их на экран. Однако у меня возникли проблемы с использованием класса вычитания фона. Я могу создать новый объект BackgroundSubtractorMOG в конструкторе, но когда я пытаюсь запустить приведенный ниже код, он принудительно завершает работу. ошибка" только 1 - и 3-канальные 8-битные изображения поддерживаются в BackgroundSubtractorMOG " из собственного кода. Я попытался изменить Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA на Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGB, и тогда это не заставит выйти, но все, что я получаю, это черный экран. Я почти уверен, что bmp по-прежнему null с 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() My 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 ответа:
Вы пробовали использовать 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++ segment_objects.cpp может быть полезен в качестве примера использования.
Надеюсь, это поможет! :)
Большое вам спасибо, ребята! И для будущих зрителей, которые придут на эту страницу, вам, возможно, придется изменить эти знания, чтобы заставить вещи работать. В SDK версии 2.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; }