Я работаю над проектом робототехники, используя телефон Android в качестве основного процессора и камеру для обнаружения движения. Я получил бинарный пакет Android от OpenCV и правильно установил его. Я могу снимать изображения с помощью собственной камеры OpenCV и отображать их на экране. Однако у меня проблемы с использованием класса вычитания фона. Я могу создать новый объект BackgroundSubtractorMOG в конструкторе, но когда я пытаюсь запустить приведенный ниже код, он принудительно завершает работу. Я получаю сообщение об ошибке «В BackgroundSubtractorMOG поддерживаются только 1- и 3-канальные 8-битные изображения» из собственного кода. Я попытался изменить Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA на Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGB, а затем он не принудительно завершил работу, но все, что я получил, это черный экран. Я почти уверен, что bmp по-прежнему равен нулю с FRAME_RGB, потому что экран остается черным, а счетчик кадров в секунду, который я рисовал сразу после растрового изображения (удален из кода, опубликованного ниже для ясности и в качестве шага по устранению неполадок), не отображается.
Я взглянул на код OpenCV C ++ для этой функции (, строка 388 здесь ), и ошибка типа изображения возникает, если тип изображения не является CV_8UC1 или CV_8UC3, поэтому я попытался использовать java CvType.CV_8UC3 вместо Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA в захвате.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);
}