LBP级联(OpenCV)将无法在Android工作室模拟器

时间:2016-01-27 03:37:43

标签: java android opencv opencv3.0 object-detection

我一直试图在我的腰带上进行一些对象跟踪,并且设法使用OpenCV 3.1在C ++中运行一个漂亮的LBP级联跟踪器。

我想尝试让这个机器人跟踪器在手机上运行,​​所以我试图将它转换到AndroidStudio。不幸的是,除了实际级联加载之外的所有东西都在工作我可以让相机在应用程序中拉出来,我可以让它显示灰度图像而不是rgb图像等。这只是级联不会加载,所以整个事情都行不通。

规格:Android Studio 1.5.1使用Opencv 3.1.0模拟API 19手机(使用x86 google apis)。

有问题的CameraActivity代码在这里 -

package <package name retracted for reasons>;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.Toast;

import java.util.Vector;

import <package name retracted here for reasons>.R;

public class CameraActivity extends Activity implements CameraBridgeViewBase.CvCameraViewListener2 {
    private static final String TAG = "OCVSample::Activity";

    private CameraBridgeViewBase mOpenCvCameraView;
    private boolean              mIsJavaCamera = true;
    private MenuItem             mItemSwitchCamera = null;

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

    public CameraActivity() {
        Log.i(TAG, "Instantiated new " + this.getClass());
    }


    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "called onCreate");
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        setContentView(R.layout.camera_surface_view);

        mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);

        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);

        mOpenCvCameraView.setCvCameraViewListener(this);


    }

    @Override
    public void onPause()
    {
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
        } else {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }

    public void onDestroy() {
        super.onDestroy();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    CascadeClassifier robot_cascade;
    public void onCameraViewStarted(int width, int height) {

        Log.d(TAG, "Trying to get robot cascade");

        robot_cascade = new CascadeClassifier(Environment.getExternalStorageDirectory().getAbsolutePath() + "/cascade.xml");
        String robot_cascade_name = Environment.getExternalStorageDirectory().getAbsolutePath() + "/cascade.xml";

        Log.d(TAG, "location is "+robot_cascade_name);

        if(robot_cascade.empty()){
            Log.d(TAG, "--(!)Error loading robot cascade");
        }
        Log.d(TAG, "Made it through loading cascade!");
    }

    public void onCameraViewStopped() {
    }

    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        Mat frameGrey = new Mat();
        Mat endFrame = new Mat();
        endFrame = inputFrame.rgba();
        MatOfRect robots = new MatOfRect();
        Imgproc.cvtColor(inputFrame.rgba(), frameGrey, Imgproc.COLOR_BGRA2GRAY);
        Imgproc.equalizeHist(frameGrey, frameGrey);

        /*robot_cascade.detectMultiScale(frameGrey, robots, 1.2, 120, 0, new Size(200, 200), new Size(300, 300));
        Log.d(TAG, "Found %x robots" + robots.toArray().length);

        for (Rect rect : robots.toArray()) {
            Imgproc.rectangle(endFrame, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0));
            Log.d(TAG, "Robot at point ( %x , %x )"+(rect.x+rect.width/2)+(rect.y+rect.height/2));
        } */

        return endFrame;
        //return inputFrame.rgba();
    }
}

目前我已将cascade.detectMultiScale注释掉,但它无效。运行它会产生:

01-26 21:07:42.085 2296-2296/? D/OCVSample::Activity: Trying to get robot cascade  
01-26 21:07:42.085 2296-2296/? D/OCVSample::Activity: location is /storage/sdcard/cascade.xml  
01-26 21:07:42.085 2296-2296/? D/OCVSample::Activity: --(!)Error loading robot cascade   
01-26 21:07:42.085 2296-2296/? D/OCVSample::Activity: Made it through loading cascade!

然后它快乐地转到onCameraFrame方法,并且目前只输出它所获得的内容(我已经能够使用它来获得灰度等等)

问题似乎出在onCameraViewStared类 -

public void onCameraViewStarted(int width, int height) {

        Log.d(TAG, "Trying to get robot cascade");
        robot_cascade = new CascadeClassifier(Environment.getExternalStorageDirectory().getAbsolutePath() + "/cascade.xml");
        String robot_cascade_name = Environment.getExternalStorageDirectory().getAbsolutePath() + "/cascade.xml";

        Log.d(TAG, "location is "+robot_cascade_name);

        if(robot_cascade.empty()){
            Log.d(TAG, "--(!)Error loading robot cascade");
        }
        Log.d(TAG, "Made it through loading cascade!");
    }

机器人级联总是空着。

我确信cascade.xml实际上是在仿真手机上 - 如果我通过adb检查,它说它在那里令人不寒而栗,并且android设备监视器也显示它就在那里。

Image Showing cascade.xml really does exist on the emulated phone

我唯一能想到的是ADM说权限是-rwxrwx---,但我在清单文件中有WRITE_EXTERNAL_STORAGEREAD_EXTERNAL_STORAGE权限,所以我会认为没事。 (我可能完全错了,如果我是,请纠正我。)

为了防止它变得很重要,我确实尝试chmod任何用户(不仅仅是所有者和组)可以读取/写入cascade.xml,但是它一直给我“坏模式”,无论如何我尝试了什么。 sd以可读/可写的方式安装(因为我能够首先将文件推到SD卡上),而我在su中,所以我不知道为什么它不会让我这样做。

编辑:chmod有非常奇怪的行为 - 它基本上不会做任何事情而且会安静地失败,或者它会说它是一个只读文件系统......即使我可以制作文件和目录并删除它们没问题。

编辑x2:将文件移动到/ data / local,它仍然不起作用,但chmod处理它,所以现在我拥有所有权限。仍然试图弄清楚为什么级联不会加载它。

所以是的,无法加载模拟SD卡上的级联。

1 个答案:

答案 0 :(得分:1)

所以,让它在模拟器上工作(最后)。显然,模拟器上的SD卡根本不允许chmod工作,因此我将文件移动到data/local。然后我将所有内容更改为从("./data/local/cascade.xml")读取,并在创建级联分类器后添加robot_cascade.load(".data/local/cascade.xml);。然后我取消注释实际使用级联的东西,它工作得很漂亮。

所以,新的onCameraViewStarted方法 -

public void onCameraViewStarted(int width, int height) {
    Log.d(TAG, "Prog: Trying to get robot cascade");

    File file = new File("./data/local/cascade.xml");
    boolean fileExists = file.exists();
    String fileDoesExist = String.valueOf(fileExists);

    Log.d(TAG, "Prog: Does the cascade file exist? "+fileDoesExist);

    robot_cascade = new CascadeClassifier("./data/local/cascade.xml");
    robot_cascade.load("./data/local/cascade.xml");
    String robot_cascade_name = "./data/local/cascade.xml";

    Log.d(TAG, "Prog: location is "+robot_cascade_name);

    if(robot_cascade.empty()){
        Log.d(TAG, "Prog: --(!)Error loading robot cascade");
    } else {
        Log.d(TAG, "Prog: --Holy smite the cascade is actually there praise the sun");
    }
    Log.d(TAG, "Prog: Made it through loading cascade!");
}

当然,现在我试图让它在手机上工作而不是模仿而且这不起作用,但那是一个不同的问题。