Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Problem when training SVM with ORB descriptors

Hello guys!

I have a folder with 20 positive and 10 negative images and I'm trying to train an SVM through the image descriptors using ORB. I'm getting the following error when calling svm.TrainAuto:

E/cv::error(): OpenCV(3.4.1) Error: Assertion failed (samples.type() == 5 || samples.type() == 4) in void cv::ml::TrainDataImpl::setData(cv::InputArray, int, cv::InputArray, cv::InputArray, cv::InputArray, cv::InputArray, cv::InputArray, cv::InputArray), file /build/master_pack-android/opencv/modules/ml/src/data.cpp, line 259

E/org.opencv.ml: ml::trainAuto_11() caught cv::Exception: OpenCV(3.4.1) /build/master_pack-android/opencv/modules/ml/src/data.cpp:259: error: (-215) samples.type() == 5 || samples.type() == 4 in function void cv::ml::TrainDataImpl::setData(cv::InputArray, int, cv::InputArray, cv::InputArray, cv::InputArray, cv::InputArray, cv::InputArray, cv::InputArray)

The code I'm using is below:

public class TrainingActivity extends Activity {

private final String TAG = "OpenCV";

private Button mTrainingButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_training);

    mTrainingButton = findViewById(R.id.trainingButton);
}

@Override
protected void onResume() {
    super.onResume();
    initOpenCV();
}

public void onTrainingButtonClick(View view) {
    train();
}

private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback() {
    @Override
    public void onManagerConnected(int status) {
        switch (status) {
            case LoaderCallbackInterface.SUCCESS:
                onLoaderCallbackSuccess();
                break;
            default:
                super.onManagerConnected(status);
        }
    }
};

private void initOpenCV() {
    if (OpenCVLoader.initDebug())
        mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
    else
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_4_0, this, mLoaderCallback);
}

private void onLoaderCallbackSuccess() {
    mTrainingButton.setVisibility(View.VISIBLE);
}

private void train() {

    final ORB orb = ORB.create();

    Mat extractorTrainingData = new Mat();
    Mat extractorTrainingLabel = new Mat();

    String path = "/OpenCV/training/open/positives";

    File[] files = FileHelper.getFiles(path);

    // Positives

    for (File file : files) {

        try {
            Mat image = Imgcodecs.imread(file.getAbsolutePath());

            Mat grayImage = new Mat();
            Imgproc.cvtColor(image, grayImage, Imgproc.COLOR_RGB2GRAY);

            Log.d(TAG, grayImage.dump());

            MatOfKeyPoint keyPoints = new MatOfKeyPoint();
            orb.detect(grayImage, keyPoints);

            Log.d(TAG, keyPoints.dump());

            MatOfFloat descriptors = new MatOfFloat();
            orb.compute(grayImage, keyPoints, descriptors);

            Log.d(TAG, descriptors.dump());

            extractorTrainingData.push_back(descriptors);
            extractorTrainingLabel.push_back(Mat.ones(new Size(1, 1), CvType.CV_32S));

        } catch (Exception e) {
            Log.d(TAG, e.getMessage());
        }
    }

    path = "/OpenCV/training/open/negatives";

    files = FileHelper.getFiles(path);

    // Negatives

    for (File file : files) {

        try {
            Mat image = Imgcodecs.imread(file.getAbsolutePath());

            Mat grayImage = new Mat();
            Imgproc.cvtColor(image, grayImage, Imgproc.COLOR_RGB2GRAY);

            Log.d(TAG, grayImage.dump());

            MatOfKeyPoint keyPoints = new MatOfKeyPoint();
            orb.detect(grayImage, keyPoints);

            Log.d(TAG, keyPoints.dump());

            MatOfFloat descriptors = new MatOfFloat();
            orb.compute(grayImage, keyPoints, descriptors);

            Log.d(TAG, descriptors.dump());

            extractorTrainingData.push_back(descriptors);
            extractorTrainingLabel.push_back(Mat.zeros(new Size(1, 1), CvType.CV_32S));

        } catch (Exception e) {
            Log.d(TAG, e.getMessage());
        }
    }

    try {

        SVM svm = SVM.create();
        svm.setKernel(SVM.RBF);
        svm.setType(SVM.C_SVC);

        //Mat mat = extractorTrainingData.reshape(1, 1);

        //Boolean result = svm.trainAuto(
        //        mat, Ml.ROW_SAMPLE, extractorTrainingLabel);

        Boolean result = svm.trainAuto(
                extractorTrainingData, Ml.ROW_SAMPLE, extractorTrainingLabel);

        String xml = Environment
                .getExternalStorageDirectory() + "/images/svm.xml";

        if (result)
            svm.save(xml);

    } catch (Exception e) {
        Log.d(TAG, e.getMessage());
    }
}

}

I've tried using the reshape function in these settings:

Mat mat = extractorTrainingData.reshape(1, 1);
Boolean result = svm.trainAuto(mat, Ml.ROW_SAMPLE, extractorTrainingLabel);

Mat mat = extractorTrainingData.reshape(extractorTrainingData.cols(), 1);
Boolean result = svm.trainAuto(mat, Ml.ROW_SAMPLE, extractorTrainingLabel);

Mat mat = extractorTrainingData.reshape(1, extractorTrainingData.rows());
Boolean result = svm.trainAuto(mat, Ml.ROW_SAMPLE, extractorTrainingLabel);

However, I still get the same error. I do not know what I can do to make it work. I'm using Android 7.1.1, OpenCV 3.4.1, Android Studio 3.0.2

Thank you!