Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

BagOfWords works in C #, but not in C ++

Hello guys,

As suggested in this post, I implemented in C++, the same method I used to train my SVM in C #. Initially, I load the vocabulary generated by the program in C# through a JNI call in C++, because the FileStorage class is not available in OpenCV4Android:

JNIEXPORT
void JNICALL Java_test_vision_MainActivity_loadVocabulary(
        JNIEnv* env,
        jobject,
        jstring vocabularyPath,
        jlong addrVocabulary)
{
    const char *str = env->GetStringUTFChars(vocabularyPath, 0);

    Mat& vocabulary = *(Mat*)addrVocabulary;

    cv::FileStorage opencv_file(str, cv::FileStorage::READ);
    opencv_file["vocabulary"] >> vocabulary;
    opencv_file.release();
}

After that, I load an image through Java, and pass the Mat object to a second C++ method, which has all the implementation of BagOfWords and SVM Predict.

Java:

Mat image = Utils.loadResource(MainActivity.this, R.raw.image, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);

predict(trainedData,
            vocabularyMat.getNativeObjAddr(),
            image.getNativeObjAddr(),
            bowDescriptor.getNativeObjAddr());

C++

JNIEXPORT
void JNICALL Java_test_vision_MainActivity_predict(
        JNIEnv* env,
        jobject,
        jstring trainedData,
        jlong addrVocabulary,
        jlong addrRgba,
        jlong addrBowDescriptor) {

    const char *str = env->GetStringUTFChars(trainedData, 0);

    Mat& vocabulary = *(Mat*)addrVocabulary;
    Mat& bowDescriptor = *(Mat*)addrBowDescriptor;

    int dictionarySize = 32;

    Ptr<DescriptorExtractor> extractor = KAZE::create();

    Ptr<BFMatcher> bFMatcher = new BFMatcher(cv::NORM_L2);

    Ptr<BOWKMeansTrainer> bOWKMeansTrainer
            = new BOWKMeansTrainer(
                    dictionarySize,
                    TermCriteria(
                            TermCriteria::MAX_ITER +
                            TermCriteria::EPS,
                            10,
                            0.0001),
                    1, KMEANS_PP_CENTERS);

    Ptr<BOWImgDescriptorExtractor> bOWImgDescriptorExtractor =
            new BOWImgDescriptorExtractor(extractor, bFMatcher);

    Ptr<ml::SVM> svm = ml::SVM::create();
    svm->setType(ml::SVM::C_SVC);
    svm->load(str);

    bOWImgDescriptorExtractor->setVocabulary(vocabulary);

    std::vector<KeyPoint> keyPoints;

    Mat& src = *(Mat*)addrRgba;

    try {
        extractor->detect(src, keyPoints);
        bOWImgDescriptorExtractor->compute(src, keyPoints, bowDescriptor);
    } catch(exception& e) {
        const char *teste = e.what();
        cout << teste;
    }

    float response = svm->predict(bowDescriptor);

    cout << response;
}

However, I have received this error when calling bOWImgDescriptorExtractor.compute:

"OpenCV(3.4.3) /build/3_4_pack-android/opencv/modules/core/src/batch_distance.cpp:238: error: (-215:Assertion failed) type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U) in function 'void cv::batchDistance(cv::InputArray, cv::InputArray, cv::OutputArray, int, cv::OutputArray, int, int, cv::InputArray, int, bool)'\n"

Sorry for the size of the question, but I tried to put as much information as possible.

Thank you.

BagOfWords works in C #, but not in C ++

Hello guys,

As suggested in this post, I implemented in C++, the same method I used to train my SVM in C #. Initially, I load the vocabulary generated by the program in C# through a JNI call in C++, because the FileStorage class is not available in OpenCV4Android:

JNIEXPORT
void JNICALL Java_test_vision_MainActivity_loadVocabulary(
        JNIEnv* env,
        jobject,
        jstring vocabularyPath,
        jlong addrVocabulary)
{
    const char *str = env->GetStringUTFChars(vocabularyPath, 0);

    Mat& vocabulary = *(Mat*)addrVocabulary;

    cv::FileStorage opencv_file(str, cv::FileStorage::READ);
    opencv_file["vocabulary"] >> vocabulary;
    opencv_file.release();
}

After that, I load an image through Java, and pass the Mat object to a second C++ method, which has all the implementation of BagOfWords and SVM Predict.

Java:

Mat image = Utils.loadResource(MainActivity.this, R.raw.image, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);

predict(trainedData,
            vocabularyMat.getNativeObjAddr(),
            image.getNativeObjAddr(),
            bowDescriptor.getNativeObjAddr());

C++

JNIEXPORT
void JNICALL Java_test_vision_MainActivity_predict(
        JNIEnv* env,
        jobject,
        jstring trainedData,
        jlong addrVocabulary,
        jlong addrRgba,
        jlong addrBowDescriptor) {

    const char *str = env->GetStringUTFChars(trainedData, 0);

    Mat& vocabulary = *(Mat*)addrVocabulary;
    Mat& bowDescriptor = *(Mat*)addrBowDescriptor;

    int dictionarySize = 32;

    Ptr<DescriptorExtractor> extractor = KAZE::create();

    Ptr<BFMatcher> bFMatcher = new BFMatcher(cv::NORM_L2);

    Ptr<BOWKMeansTrainer> bOWKMeansTrainer
            = new BOWKMeansTrainer(
                    dictionarySize,
                    TermCriteria(
                            TermCriteria::MAX_ITER +
                            TermCriteria::EPS,
                            10,
                            0.0001),
                    1, KMEANS_PP_CENTERS);

    Ptr<BOWImgDescriptorExtractor> bOWImgDescriptorExtractor =
            new BOWImgDescriptorExtractor(extractor, bFMatcher);

    Ptr<ml::SVM> svm = ml::SVM::create();
    svm->setType(ml::SVM::C_SVC);
    svm->load(str);

    bOWImgDescriptorExtractor->setVocabulary(vocabulary);

    std::vector<KeyPoint> keyPoints;

    Mat& src = *(Mat*)addrRgba;

    try {
        extractor->detect(src, keyPoints);
        bOWImgDescriptorExtractor->compute(src, keyPoints, bowDescriptor);
    } catch(exception& e) {
        const char *teste = e.what();
        cout << teste;
    }

    float response = svm->predict(bowDescriptor);

    cout << response;
}

However, I have received this error when calling bOWImgDescriptorExtractor.compute:

"OpenCV(3.4.3) /build/3_4_pack-android/opencv/modules/core/src/batch_distance.cpp:238: error: (-215:Assertion failed) type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U) in function 'void cv::batchDistance(cv::InputArray, cv::InputArray, cv::OutputArray, int, cv::OutputArray, int, int, cv::InputArray, int, bool)'\n"

Sorry for the size of the question, but I tried to put as much information as possible.

Thank you.