LBP Cascade (OpenCV) won't load on android studio emulator
<p>I've been trying to get some object tracking under my belt, and I managed to get a nice LBP cascade tracker running in C++, using OpenCV 3.1.</p>

<p>I wanted to try and get this robot tracker running on a phone, so I'm trying to transition it over to AndroidStudio. Unfortunately, everything except the actual cascade loading is working. I can get the camera to pull up in the app, I can have it show off the greyscale image instead of an rgb image, etc. It's just that cascade won't load, so the whole thing won't work. </p>

<p>Specs: Android Studio 1.5.1 emulating a API 19 phone (using the x86 google apis), using Opencv 3.1.0. </p>

<p>The CameraActivity code in question is here - </p>

<pre><code>package &lt;package name retracted for reasons&gt;;

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 &lt;package name retracted here for reasons&gt;.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();
    }
}
</code></pre>

<p>For right now I have the <code>cascade.detectMultiScale</code> commented out while it's not working. Running it yields:</p>

<pre><code>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!
</code></pre>

<p>And then it goes down to the onCameraFrame method happily, and currently just outputs what it's getting (I've been able to play with it to get grayscale out and so on)</p>

<p>The problem appears to be in the onCameraViewStared class - </p>

<pre><code>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!");
    }
</code></pre>

<p>Robot cascade always comes up empty. </p>

<p>I am sure that the cascade.xml is actually on the emulated phone - if I check through adb, it says it's chilling right there, and the android device monitor also shows that it's there. </p>

<p><a href="https://i.stack.imgur.com/f9kye.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/f9kye.png" alt="Image Showing cascade.xml really does exist on the emulated phone"></a></p>

<p>The only thing I can think of is that ADM says that the permissions are <code>-rwxrwx---</code>, but I've got the <code>WRITE_EXTERNAL_STORAGE</code> and <code>READ_EXTERNAL_STORAGE</code> permissions in the manifest file, so I would think that'd be fine. (I could be completely wrong though, please correct me if I am).</p>

<p>Just in case it was important, I did try to <code>chmod</code> the cascade.xml to be read/writable by any user (not just owner and group), but it kept giving me "Bad Mode" no matter what I tried. The sd is mounted as read/writeable (because I was able to push the file onto the sd card in the first place), and I was in su, so I have no idea why it won't let me do that. </p>

<p>Edit: <code>chmod</code> is having really strange behavior - it basically won't do anything and fail quietly, or it'll say that it's a read-only file system... even though I can make files and directories and delete them no problem. </p>

<p>Edit x2: Moved file to /data/local, and it still doesn't work, but <code>chmod</code> worked on it so now I have all permissions. Still trying to figure out why cascade won't load it though.</p>

<p>So yeah, can't load a cascade that is definitely on the emulated sd card. </p>