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.