如何从Android相机中找到帧的轮廓并将其转换为box2d实体?

如何从Android相机中找到帧的轮廓并将其转换为box2d实体?,android,opencv,computer-vision,jbox2d,Android,Opencv,Computer Vision,Jbox2d,使用OpenFrameworks,OpenCV和Box2DI能够以良好的帧速率实现它。使用Android似乎是一项复杂得多的任务(部分原因是我是JAVA新手) 我是这样开始的: 使用“OpenCV示例-图像操作”,删除除“canny”效果之外的所有内容,该效果可生成一个很好的黑白图像,非常适合查找轮廓 public Mat onCameraFrame(CvCameraViewFrame inputFrame) { mRgba = inputFrame.rgba(); Imgpro

使用OpenFrameworks,OpenCV和Box2DI能够以良好的帧速率实现它。使用Android似乎是一项复杂得多的任务(部分原因是我是JAVA新手)

我是这样开始的:

  • 使用“OpenCV示例-图像操作”,删除除“canny”效果之外的所有内容,该效果可生成一个很好的黑白图像,非常适合查找轮廓

    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样本-颜色斑点检测”中,我抓住了逻辑来查找垫子中的轮廓:

    // 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);
    
    //这两行实际上在onCameraViewStarted函数中
    mHierarchy=新材料();
    轮廓颜色=新标量(255,0,0255);
    //这些行在CameraFrame上起作用
    列表等高线=新的ArrayList();
    Imgproc.findContours(内部窗口、等高线、层次结构、Imgproc.RETR_外部、,
    Imgproc.链(近似简单);
    Imgproc.绘制等高线(mIntermediateMat,等高线,-1,等高线颜色);
    
    因此,我当前的函数看起来是这样的,但它不起作用:

    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;
    }
    
    public Mat onCameraFrame(CvCameraViewFrame inputFrame)
    {
    mRgba=inputFrame.rgba();
    如果((mRgbaInnerWindow==null)| |(mGrayInnerWindow==null)| |(mRgba.cols()!=mSizeRgba.width)|(mRgba.height()!=mSizeRgba.height))
    CreateAxiliaryMats();
    Imgproc.Canny(MrgbannerWindow,mIntermediateMat,50100);
    //Imgproc.cvtColor(mIntermediateMat,mrgbainerwindow,Imgproc.COLOR_gray,4);
    列表等高线=新的ArrayList();
    Imgproc.findContours(mRgbaInnerWindow、等高线、mHierarchy、Imgproc.RETR\u EXTERNAL、Imgproc.CHAIN\u APPROX\u SIMPLE);
    //Imgproc.绘制等高线(mIntermediateMat,等高线,-1,等高线颜色);
    返回mRgba;
    }
    
  • 现在,这就是我被绊倒的地方。我经常遇到例外情况,我认为我没有使用正确的尺寸或将垫子转换为正确的颜色空间。这篇文章有一些见解,但我不知道它是否正确:


  • 嗨,我也是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;
    }
    
    }
    
    导入android.app.Activity;
    导入android.os.Bundle;
    导入android.util.Log;
    导入android.view.SurfaceView;
    导入org.opencv.android.*;
    导入org.opencv.core.*;
    导入org.opencv.imgproc.imgproc;
    导入java.util.ArrayList;
    导入java.util.List;
    公共类MainActivity扩展活动实现CvCameraViewListener2{
    私有静态最终字符串标记=MainActivity.class.getCanonicalName();
    私人摄像机BridgeViewBase mOpenCvCameraView;
    私人Mat mRgba;
    私人医疗设备;
    私人马拉松;
    垫层次;
    列出等高线;
    专用BaseLoaderCallback mlLoaderCallback=新BaseLoaderCallback(此){
    @凌驾
    已连接管理器上的公共无效(int状态){
    开关(状态){
    案例加载程序CallbackInterface.SUCCESS:
    {
    Log.i(标记“OpenCV已成功加载”);
    mOpenCvCameraView.enableView();
    }中断;
    违约:
    {
    超级管理器已连接(状态);
    }中断;
    }
    }
    };
    @凌驾
    创建时受保护的void(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mOpenCvCameraView=(CameraBridgeViewBase)findViewById(R.id.java\u surface\u view);
    mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
    mOpenCvCameraView.setCvCameraViewListener(本);
    }
    @凌驾
    恢复时公开作废(){
    super.onResume();
    OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3,
    mLoaderCallback);
    }
    @凌驾
    公共无效暂停(){
    super.onPause();
    if(mOpenCvCameraView!=null)
    mOpenCvCameraView.disableView();
    }
    @凌驾
    开始时的公共空隙(整数宽度、整数高度){
    mRgba=新垫(高度、宽度、CvType.CV_8UC4);
    mIntermediateMat=新垫(高度、宽度、CvType.CV_8UC4);
    mGray=新垫(高度、宽度、CvType.CV_8UC1);
    层次结构=新的Mat();
    }
    @凌驾
    CAMERAVIEWSTOPPED()上的公共空白{
    mRgba.release();
    mGray.release();
    mIntermediateMat.release();
    hierarchy.release();
    }
    @凌驾
    CameraFrame上的公用Mat(CvCameraViewFrame输入框){
    mRgba=inputFrame.gray();
    等高线=新的ArrayList();
    层次结构=新的Mat();
    Imgproc.Canny(mRgba,mIntermediateMat,80100);
    Imgproc.findContours(mIntermediateMat、等高线、层次、Imgproc.RETR_树、Imgproc.CHAIN_近似、简单、新点(0,0));
    /*材料图纸=材料零点(最小中间材料尺寸(),CvType.CV_8UC3);
    对于(int i=0;i

    我知道这可能不是实现这一目标的最佳方式,但我们都在这里学习新的方法:)

    简短回答:您必须使用
    Canny
    的结果作为
    findContetors
    的输入(第一个参数),即

    Imgproc.findContours(mIntermediateMat, ...);
    

    您使用的是什么box2d实现?它只是裸体的jbox2d吗?或者您正在使用类似于ANDEngine的东西?我一直在研究ANDEngine,但我还不知道如何使用ANDEngine的SimpleGameActivity实现CVCamera类。这会导致Canny检测不断闪烁是的,有人有更好的示例来避免闪烁?可能是因为它是实时的。