Как найти контуры кадра с камеры Android и преобразовать их в тела box2d?
Используя OpenFrameworks, OpenCV и Box2D, я смог добиться этого с хорошей частотой кадров. Использование Android кажется гораздо более сложной задачей (отчасти потому, что я новичок в JAVA).
Вот как я начал:
Используйте "Образец OpenCV - манипуляции с изображениями" и удалите все, кроме эффекта "хитрый", который создает хорошее черно-белое изображение, которое идеально подходит для поиска контуров.
public Mat onCameraFrame(CvCameraViewFrame inputFrame) { mRgba = inputFrame.rgba(); Imgproc.Canny(mRgbaInnerWindow, mIntermediateMat, 50, 100); Imgproc.cvtColor(mIntermediateMat, mRgbaInnerWindow, Imgproc.COLOR_GRAY2BGRA, 4); return mRgba; }
Из "OpenCV Sample - color-blob-Detection" я взял логику, чтобы найти контуры в мате:
// These two lines are actually in the function onCameraViewStarted mHierarchy = new Mat(); CONTOUR_COLOR = new Scalar(255,0,0,255); // These lines are in function onCameraFrame List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); Imgproc.findContours(mRgbaInnerWindow, contours, mHierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); Imgproc.drawContours(mIntermediateMat, contours, -1, CONTOUR_COLOR);
Итак, моя текущая функция выглядит так, и она не работает:
public Mat onCameraFrame(CvCameraViewFrame inputFrame) { mRgba = inputFrame.rgba(); if ((mRgbaInnerWindow == null) || (mGrayInnerWindow == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height)) CreateAuxiliaryMats(); Imgproc.Canny(mRgbaInnerWindow, mIntermediateMat, 50, 100); //Imgproc.cvtColor(mIntermediateMat, mRgbaInnerWindow, Imgproc.COLOR_GRAY2BGRA, 4); List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); Imgproc.findContours(mRgbaInnerWindow, contours, mHierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); //Imgproc.drawContours(mIntermediateMat, contours, -1, CONTOUR_COLOR); return mRgba; }
Вот где я застрял. Я продолжаю получать исключения, и я думаю, что я не использую правильные размеры или преобразовываю Мат в правильное цветовое пространство. В этом посте есть некоторое понимание, но я не знаю, правильно ли это: OpenCV на Android findContours выдает исключение
2 ответа
Привет, я тоже новичок в openCV, но этот код может помочь,
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;
import org.opencv.android.*;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity implements CvCameraViewListener2{
private static final String TAG = MainActivity.class.getCanonicalName();
private CameraBridgeViewBase mOpenCvCameraView;
private Mat mRgba;
private Mat mIntermediateMat;
private Mat mGray;
Mat hierarchy;
List<MatOfPoint> contours;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
mOpenCvCameraView.enableView();
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.java_surface_view);
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
}
@Override
public void onResume() {
super.onResume();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this,
mLoaderCallback);
}
@Override
public void onPause() {
super.onPause();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
@Override
public void onCameraViewStarted(int width, int height) {
mRgba = new Mat(height, width, CvType.CV_8UC4);
mIntermediateMat = new Mat(height, width, CvType.CV_8UC4);
mGray = new Mat(height, width, CvType.CV_8UC1);
hierarchy = new Mat();
}
@Override
public void onCameraViewStopped() {
mRgba.release();
mGray.release();
mIntermediateMat.release();
hierarchy.release();
}
@Override
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba = inputFrame.gray();
contours = new ArrayList<MatOfPoint>();
hierarchy = new Mat();
Imgproc.Canny(mRgba, mIntermediateMat, 80, 100);
Imgproc.findContours(mIntermediateMat, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0));
/* Mat drawing = Mat.zeros( mIntermediateMat.size(), CvType.CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{
Scalar color =new Scalar(Math.random()*255, Math.random()*255, Math.random()*255);
Imgproc.drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, new Point() );
}*/
hierarchy.release();
Imgproc.drawContours(mRgba, contours, -1, new Scalar(Math.random()*255, Math.random()*255, Math.random()*255));//, 2, 8, hierarchy, 0, new Point());
// Imgproc.cvtColor(mIntermediateMat, mRgba, Imgproc.COLOR_GRAY2RGBA, 4);
return mRgba;
}
}
Я знаю, что это не лучший способ для достижения этой цели, но мы все здесь, чтобы изучить новые пути:)
Краткий ответ: Вы должны использовать результат Canny
в качестве входных данных (1-й аргумент) для findContours
т.е.
Imgproc.findContours(mIntermediateMat, ...);