Использование собственных функций в Android с OpenCV

Я хочу использовать OpenCV + Android, используя собственные функции. Однако я немного запутался, как использовать растровые изображения в качестве параметров и как вернуть значение отредактированного растрового изображения (или Mat).

Так, например, у меня есть собственная функция:

#include <jni.h> #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> JNIEXPORT ??? JNICALL Java_com_my_package_name_and_javaclass_myFunction(JNIEnv* env, jobject javaThis, cv::Mat mat1){ //here will be code to perform filtering, blurring, canny edge detection or similar things. //so I want to input a bitmap, edit it and send it back to the Android class. return ??? } 

Поэтому здесь я использую cv :: Mat как параметр. Я знаю, что это неправильно, но я не уверен, что это должно быть, и что должно быть в соответствующем классе java. Должен ли он быть ByteArray? А затем в вышеупомянутой нативной функции параметр будет jByteArray (или аналогичным)?

А для возвращаемого объекта, что я должен положить? Должно ли это быть массивом?

В основном то, что я ищу, есть в Java-классе. У меня есть Mat (или Bitmap), я отправляю его на нативную функцию для редактирования и возвращает хорошо отредактированное растровое изображение.

Это код OpenCV Tutorial для Android. Я помню, что мне понадобилось время, чтобы понять конвенцию JNI. Просто сначала ознакомьтесь с кодом JNI

 #include <jni.h> #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/features2d/features2d.hpp> #include <vector> using namespace std; using namespace cv; extern "C" { JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial3_Sample3View_FindFeatures(JNIEnv* env, jobject thiz, jint width, jint height, jbyteArray yuv, jintArray bgra) { jbyte* _yuv = env->GetByteArrayElements(yuv, 0); jint* _bgra = env->GetIntArrayElements(bgra, 0); Mat myuv(height + height/2, width, CV_8UC1, (unsigned char *)_yuv); Mat mbgra(height, width, CV_8UC4, (unsigned char *)_bgra); Mat mgray(height, width, CV_8UC1, (unsigned char *)_yuv); //Please make attention about BGRA byte order //ARGB stored in java as int array becomes BGRA at native level cvtColor(myuv, mbgra, CV_YUV420sp2BGR, 4); vector<KeyPoint> v; FastFeatureDetector detector(50); detector.detect(mgray, v); for( size_t i = 0; i < v.size(); i++ ) circle(mbgra, Point(v[i].pt.x, v[i].pt.y), 10, Scalar(0,0,255,255)); env->ReleaseIntArrayElements(bgra, _bgra, 0); env->ReleaseByteArrayElements(yuv, _yuv, 0); } } 

А затем код Java

 package org.opencv.samples.tutorial3; import android.content.Context; import android.graphics.Bitmap; class Sample3View extends SampleViewBase { public Sample3View(Context context) { super(context); } @Override protected Bitmap processFrame(byte[] data) { int frameSize = getFrameWidth() * getFrameHeight(); int[] rgba = new int[frameSize]; FindFeatures(getFrameWidth(), getFrameHeight(), data, rgba); Bitmap bmp = Bitmap.createBitmap(getFrameWidth(), getFrameHeight(), Bitmap.Config.ARGB_8888); bmp.setPixels(rgba, 0/* offset */, getFrameWidth() /* stride */, 0, 0, getFrameWidth(), getFrameHeight()); return bmp; } public native void FindFeatures(int width, int height, byte yuv[], int[] rgba); static { System.loadLibrary("native_sample"); } } 

Вам лучше читать стандартные образцы OpenCV для Android (родные).

Конечно, вы не можете использовать параметр cv::Mat as, потому что это класс c ++, а не java. Однако, если я не ошибаюсь, вы можете вызывать методы класса c ++ из источника java (он также является частью JNI).

В вашей ситуации вы должны использовать указатель на данные изображения (это может быть uchar* или int* в c ++, это то же самое, что и byte[] или int[] в java). Например, вы можете получить пиксели из Android Bitmap с помощью метода getPixels . И в c ++ вы можете использовать конкретный конструктор mat, который принимает указатель на данные изображения:

 // constructor for matrix headers pointing to user-allocated data Mat(int _rows, int _cols, int _type, void* _data, size_t _step=AUTO_STEP); Mat(Size _size, int _type, void* _data, size_t _step=AUTO_STEP); 

Надеюсь, поможет.