I want to use SWT(Stroke Width Transform) algorithm to improve Tesseract-OCR accuracy. I referred to this link.
I found ccv and a way to use it.
I want to use ccv_swt method, but I don't know how to use exactly.
Especially, ccv_swt_param_t params part.
This is my code.
MainActivity.java
private Mat matInput;
private Mat matGray;
public native void ocrTest(long matAddrGray, long matAddrCanny, long matAddrBlur);
#Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
matInput = inputFrame.rgba();
Imgproc.cvtColor(matInput, matGray, Imgproc.COLOR_RGB2GRAY);
ocrTest(matGray.getNativeObjAddr(), matCanny.getNativeObjAddr(), matBlur.getNativeObjAddr());
}
native-lib.cpp
extern "C"
JNIEXPORT void JNICALL
Java_com_example_ocrtest_MainActivity_ocrTest(JNIEnv *env, jobject instance, jlong matAddrGray,
jlong matAddrCanny, jlong matAddrBlur) {
// TODO
Mat &matGray = *(Mat *) matAddrGray;
Mat &matCanny = *(Mat *) matAddrCanny;
Mat &matBlur = *(Mat *) matAddrBlur;
int lowThreshold = 50;
int highThreshold = 150;
Canny(matGray, matCanny, lowThreshold, highThreshold, 3);
blur(matGray, matBlur, Size(3, 3));
}
Related
I am trying to detect facial landmark using opencv ,dlib library in android studio.
I can capture image and detect landmarks from the image.
But I am facing problem when I am trying to detect facial landmark in real time.
Because I am deserializing shape_predictor_68_face_landmarks.dat file for each frame.
onCameraFrame method of MainActivity.Java
#Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame)
{
matInput =inputFrame.rgba();
NativeClass.LandmarkDetection(matInput.getNativeObjAddr(), matOutput.getNativeObjAddr());
return matOutput;
}
NativeClass.Java
package com.example.user.drowsinessdetection;
public class NativeClass {
public native static String getMessage();
public native static void LandmarkDetection(long addrInput,long addrOutput);
}
The cpp file for Landmark detection:
com_example_user_drowsinessdetection_NativeClass.cpp
#include <com_example_user_drowsinessdetection_NativeClass.h>
#include <dlib/geometry/rectangle.h>
JNIEXPORT jstring JNICALL
Java_com_example_user_drowsinessdetection_NativeClass_getMessage
(JNIEnv *env, jclass){
env->NewStringUTF("JNI message");
}
JNIEXPORT void JNICALL
Java_com_example_user_drowsinessdetection_NativeClass_LandmarkDetection
(JNIEnv *env, jclass thiz, jlong addrInput, jlong addrOutput){
Mat& image = *(Mat*)addrInput;
Mat& dst = *(Mat*)addrOutput;
faceDetectionDlib(image, dst);
}
void faceDetectionDlib(Mat& img, Mat& dst){
try {
frontal_face_detector detector = get_frontal_face_detector();
shape_predictor pose_model;
deserialize("storage/emulated/0/shape_predictor_68_face_landmarks.dat")>>pose_model;
cv_image<bgr_pixel>cimg(img);
std::vector<dlib::rectangle> faces = detector(cimg);
std::vector<full_object_detection> shapes;
int k=faces.size();
for(unsigned long i = 0;i < k; ++i)
shapes.push_back(pose_model(cimg,faces[i]));
dst = img.clone();
renderToMat(shapes, dst);
}
catch (serialization_error& e)
{
cout<<endl<<e.what()<<endl;
}
}
void renderToMat(std::vector<full_object_detection>& dets, Mat& dst){
Scalar color;
int sz = 3,l;
color = Scalar(0,255,0);
//chin line
l=dets.size();
for(unsigned long idx = 0; idx < l; idx++) {
//left eye
for (unsigned long i = 37; i <= 41; ++i)
cv::line(dst, Point(dets[idx].part(i).x(), dets[idx].part(i).y()),
Point(dets[idx].part(i - 1).x(), dets[idx].part(i - 1).y()), color, sz);
cv::line(dst, Point(dets[idx].part(36).x(), dets[idx].part(36).y()),
Point(dets[idx].part(41).x(), dets[idx].part(41).y()), color, sz);
//right eye
for (unsigned long i = 43; i <= 47; ++i)
cv::line(dst, Point(dets[idx].part(i).x(), dets[idx].part(i).y()),
Point(dets[idx].part(i - 1).x(), dets[idx].part(i - 1).y()), color, sz);
cv::line(dst, Point(dets[idx].part(42).x(), dets[idx].part(42).y()),
Point(dets[idx].part(47).x(), dets[idx].part(47).y()), color, sz);
//lips out part
}
}
I don't want execute this line
frontal_face_detector detector = get_frontal_face_detector();
and
deserialize("storage/emulated/0/shape_predictor_68_face_landmarks.dat")>>pose_model;
for each and every frame.
So How can I do these only once and then use these for all other frames?
I am a newbie.
Please help.
Sorry for my poor English. :)
It seems that opencv can't use native camera on Android 5.+ ( lollipop ).
cf :
http://code.opencv.org/issues/4185
Is there an other way to grab pictures from a native activity and then convert into cv::mat ?
Or, maybe I could use jni to call a grab function in java from my c++ activity ?
Thank you for your help
Charles
You could use jni to call a grab function in java from c++ activity, like this(threshold example):
Java code:
//Override JavaCameraView OpenCV function
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba();
mGray = inputFrame.gray();
ProcessImage.threshold(mGray, mGray, 97, 0);
return mGray;
}
// Your functions
public static void threshold(Mat srcGray, Mat dst, int thresholdValue, int thresholdType) {
nativeThreshold(srcGray.getNativeObjAddr(), dst.getNativeObjAddr(), thresholdValue, thresholdType.ordinal());
}
private static native void nativeThreshold(long srcGray, long dst, int thresholdValue, int thresholdType);
JNI c++ code:
JNIEXPORT void JNICALL Java_{package}_nativeThreshold
(JNIEnv * jenv, jobject jobj, jlong scrGray, jlong dst, jint thresholdValue, jint thresholdType)
{
try
{
Mat matDst = *((Mat*)dst);
Mat matSrcGray = *((Mat*)scrGray);
threshold( matSrcGray, matDst, thresholdValue, max_BINARY_value, thresholdType );
}
catch(cv::Exception& e)
{
LOGD("nativeThreshold caught cv::Exception: %s", e.what());
jclass je = jenv->FindClass("org/opencv/core/CvException");
if(!je)
je = jenv->FindClass("java/lang/Exception");
jenv->ThrowNew(je, e.what());
}
catch (...)
{
LOGD("nativeThreshold caught unknown exception");
jclass je = jenv->FindClass("java/lang/Exception");
jenv->ThrowNew(je, "Unknown exception in JNI code ProcessImage.nativeThreshold()");
}
}
Hope this helps!
I am using opencv-sdk-android.
I want that my native code should return keypoint vector. Is it correct to use code like this..
Vector<KeyPoint> keypoint = FindFeatures(Gray1.getNativeObjAddr(),descriptor.getNativeObjAddr());
and
public native Vector<KeyPoint> FindFeatures(long matAddrGr1, long matAddrGr2);
My natice code is
extern "C" {
JNIEXPORT Vector<KeyPoint> JNICALL Java_com_example_xyz_MainActivity_FindFeatures(JNIEnv*, jobject, jlong addrGray1, jlong addrdescrptor);
JNIEXPORT Vector<KeyPoint> JNICALL Java_com_example_xyz_MainActivity_FindFeatures(JNIEnv*, jobject, jlong addrGray1, jlong addrdescrptor)
{
Mat& mGr1 = *(Mat*)addrGray1;
Mat& descriptors_1 = *(Mat*)addrdescrptor;
vector<KeyPoint> keypoint_1;
//Do some processing here..
return keypoint_1;
}
}
If not please suggest me some altenative way to achieve it. am new in opencv.
I had the same problem and I solved it with this piece of code.
First of all in java code I've declared the function FindFeatures like this:
public native KeyPoint[] FindFeatures(long matAddrGr1, long matAddrGr2);
And my native code is:
JNIEXPORT jobjectArray JNICALL Java_com_example_mipatternrecognition_Reconocimiento_FindFeatures(
JNIEnv* env, jobject, jlong matAddrGr1, jlong matAddrGr2) {
Mat& mGr = *(Mat*) matAddrGr1;
Mat& mRgb = *(Mat*) matAddrGr2;
vector < KeyPoint > keyPoints_1;
//Do some processing...
// Get a class reference for org/opencv/features2d/KeyPoint
jclass cls = env->FindClass("org/opencv/features2d/KeyPoint");
// Get the Method ID of the constructor (Float,Float,Float,Float,Float,Integer,Integer)
jmethodID midInit = env->GetMethodID(cls, "<init>", "(FFFFFII)V");
// Call back constructor to allocate a new instance
jobjectArray newKeyPointArr = env->NewObjectArray(keyPoints_1.size(), cls, NULL);
for (unsigned int i = 0; i < keyPoints_1.size(); i++) {
jobject newKeyPoint = env->NewObject(cls, midInit, keyPoints_1[i].pt.x,
keyPoints_1[i].pt.y, keyPoints_1[i].size, keyPoints_1[i].angle,
keyPoints_1[i].response, keyPoints_1[i].octave,
keyPoints_1[i].class_id);
env->SetObjectArrayElement(newKeyPointArr, i, newKeyPoint);
}
return newKeyPointArr;
}
I hope it helps to you...
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Background
most of the times, getting OOM on android is due to using too many bitmaps and/or creating large bitmaps.
recently i've decided to try out JNI in order to allow avoiding OOM by storing the data itself on the JNI side.
after messing around with JNI for a while, i've created some posts on SO asking for help and sharing my knowledge, and i've now decided to share some more code with you. here are the posts in case anyone is interested in reading the findings or contributing :
How to cache bitmaps into native memory
image decoding and manipulation using JNI on android
JNI - how to use multiple Jni wrapper instances with different fields?
Rotating a bitmap using JNI & NDK
this time, i've added the ability to store,restore, crop and rotate bitmaps. it should be easy to add more options and I would be happy if other people here would add their own code to more useful functions .
so the code i'm about to show is actually merging of all the things i've created.
Sample code of usage:
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
final int width=bitmap.getWidth(),height=bitmap.getHeight();
// store the bitmap in the JNI "world"
final JniBitmapHolder bitmapHolder=new JniBitmapHolder(bitmap);
// no need for the bitmap on the java "world", since the operations are done on the JNI "world"
bitmap.recycle();
// crop a center square from the bitmap, from (0.25,0.25) to (0.75,0.75) of the bitmap.
bitmapHolder.cropBitmap(width/4,height/4,width*3/4,height*3/4);
//rotate the bitmap:
bitmapHolder.rotateBitmapCcw90();
//get the output java bitmap , and free the one on the JNI "world"
bitmap=bitmapHolder.getBitmapAndFree();
The project is available on github
project page is available on github here .
feel free to give advises and contribute.
Important notes
same notes as shown here, plus:
current features that are written here (more updated on the project page) :
store
restore
rotate 90 degrees CCW
crop.
the approach i've taken for this code is both memory efficiency (use only memory that i need, and free it when not needed), and CPU efficiency (i tried to use pointers and CPU memory cache optimizations whenever possible).
for best performance, i've done really few validations, especially on the JNI part. it might be best to manage the validations on the java "world".
there are still many missing features that i think should be added, and i hope that i will have the time to add them . if anyone wishes to contribute, i will be glad to add they code too. here are the functions that i think could be useful:
get current bitmap info
scale bitmaps, including choice of which algorithm to use (nearest neighbour and bilinear interpolation should be enough).
use different bitmap formats
do the decoding within JNI, to avoid creation of the java bitmap (and not use the heap on the java world) from the beginning, only at the end, when you finished with all of the operations.
face detection
rotation in any angle, or at least the obvious ones . currently i only added rotation of 90 degrees counter clock wise .
NOTE: this is a bit old code. for the most updated one, check out the project page on github.
jni/Android.mk
LOCAL_PATH := $(call my-dir)
#bitmap operations module
include $(CLEAR_VARS)
LOCAL_MODULE := JniBitmapOperations
LOCAL_SRC_FILES := JniBitmapOperations.cpp
LOCAL_LDLIBS := -llog
LOCAL_LDFLAGS += -ljnigraphics
include $(BUILD_SHARED_LIBRARY)
APP_OPTIM := debug
LOCAL_CFLAGS := -g
#if you need to add more module, do the same as the one we started with (the one with the CLEAR_VARS)
jni/JniBitmapOperations.cpp
#include <jni.h>
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <android/bitmap.h>
#include <cstring>
#include <unistd.h>
#define LOG_TAG "DEBUG"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
extern "C"
{
JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap);
JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle);
JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle);
JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniRotateBitmapCcw90(JNIEnv * env, jobject obj, jobject handle);
JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniCropBitmap(JNIEnv * env, jobject obj, jobject handle, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom);
}
class JniBitmap
{
public:
uint32_t* _storedBitmapPixels;
AndroidBitmapInfo _bitmapInfo;
JniBitmap()
{
_storedBitmapPixels = NULL;
}
};
/**crops the bitmap within to be smaller. note that no validations are done*/ //
JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniCropBitmap(JNIEnv * env, jobject obj, jobject handle, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom)
{
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
if (jniBitmap->_storedBitmapPixels == NULL)
return;
uint32_t* previousData = jniBitmap->_storedBitmapPixels;
uint32_t oldWidth = jniBitmap->_bitmapInfo.width;
uint32_t newWidth = right - left, newHeight = bottom - top;
uint32_t* newBitmapPixels = new uint32_t[newWidth * newHeight];
uint32_t* whereToGet = previousData + left + top * oldWidth;
uint32_t* whereToPut = newBitmapPixels;
for (int y = top; y < bottom; ++y)
{
memcpy(whereToPut, whereToGet, sizeof(uint32_t) * newWidth);
whereToGet += oldWidth;
whereToPut += newWidth;
}
//done copying , so replace old data with new one
delete[] previousData;
jniBitmap->_storedBitmapPixels = newBitmapPixels;
jniBitmap->_bitmapInfo.width = newWidth;
jniBitmap->_bitmapInfo.height = newHeight;
}
/**rotates the inner bitmap data by 90 degress counter clock wise*/ //
JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniRotateBitmapCcw90(JNIEnv * env, jobject obj, jobject handle)
{
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
if (jniBitmap->_storedBitmapPixels == NULL)
return;
uint32_t* previousData = jniBitmap->_storedBitmapPixels;
AndroidBitmapInfo bitmapInfo = jniBitmap->_bitmapInfo;
uint32_t* newBitmapPixels = new uint32_t[bitmapInfo.height * bitmapInfo.width];
int whereToPut = 0;
// A.D D.C
// ...>...
// B.C A.B
for (int x = bitmapInfo.width - 1; x >= 0; --x)
for (int y = 0; y < bitmapInfo.height; ++y)
{
uint32_t pixel = previousData[bitmapInfo.width * y + x];
newBitmapPixels[whereToPut++] = pixel;
}
delete[] previousData;
jniBitmap->_storedBitmapPixels = newBitmapPixels;
uint32_t temp = bitmapInfo.width;
bitmapInfo.width = bitmapInfo.height;
bitmapInfo.height = temp;
}
/**free bitmap*/ //
JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle)
{
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
if (jniBitmap->_storedBitmapPixels == NULL)
return;
delete[] jniBitmap->_storedBitmapPixels;
jniBitmap->_storedBitmapPixels = NULL;
delete jniBitmap;
}
/**restore java bitmap (from JNI data)*/ //
JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle)
{
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
if (jniBitmap->_storedBitmapPixels == NULL)
{
LOGD("no bitmap data was stored. returning null...");
return NULL;
}
//
//creating a new bitmap to put the pixels into it - using Bitmap Bitmap.createBitmap (int width, int height, Bitmap.Config config) :
//
//LOGD("creating new bitmap...");
jclass bitmapCls = env->FindClass("android/graphics/Bitmap");
jmethodID createBitmapFunction = env->GetStaticMethodID(bitmapCls, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
jstring configName = env->NewStringUTF("ARGB_8888");
jclass bitmapConfigClass = env->FindClass("android/graphics/Bitmap$Config");
jmethodID valueOfBitmapConfigFunction = env->GetStaticMethodID(bitmapConfigClass, "valueOf", "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");
jobject bitmapConfig = env->CallStaticObjectMethod(bitmapConfigClass, valueOfBitmapConfigFunction, configName);
jobject newBitmap = env->CallStaticObjectMethod(bitmapCls, createBitmapFunction, jniBitmap->_bitmapInfo.width, jniBitmap->_bitmapInfo.height, bitmapConfig);
//
// putting the pixels into the new bitmap:
//
int ret;
void* bitmapPixels;
if ((ret = AndroidBitmap_lockPixels(env, newBitmap, &bitmapPixels)) < 0)
{
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
return NULL;
}
uint32_t* newBitmapPixels = (uint32_t*) bitmapPixels;
int pixelsCount = jniBitmap->_bitmapInfo.height * jniBitmap->_bitmapInfo.width;
memcpy(newBitmapPixels, jniBitmap->_storedBitmapPixels, sizeof(uint32_t) * pixelsCount);
AndroidBitmap_unlockPixels(env, newBitmap);
//LOGD("returning the new bitmap");
return newBitmap;
}
/**store java bitmap as JNI data*/ //
JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap)
{
AndroidBitmapInfo bitmapInfo;
uint32_t* storedBitmapPixels = NULL;
//LOGD("reading bitmap info...");
int ret;
if ((ret = AndroidBitmap_getInfo(env, bitmap, &bitmapInfo)) < 0)
{
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return NULL;
}
LOGD("width:%d height:%d stride:%d", bitmapInfo.width, bitmapInfo.height, bitmapInfo.stride);
if (bitmapInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
{
LOGE("Bitmap format is not RGBA_8888!");
return NULL;
}
//
//read pixels of bitmap into native memory :
//
//LOGD("reading bitmap pixels...");
void* bitmapPixels;
if ((ret = AndroidBitmap_lockPixels(env, bitmap, &bitmapPixels)) < 0)
{
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
return NULL;
}
uint32_t* src = (uint32_t*) bitmapPixels;
storedBitmapPixels = new uint32_t[bitmapInfo.height * bitmapInfo.width];
int pixelsCount = bitmapInfo.height * bitmapInfo.width;
memcpy(storedBitmapPixels, src, sizeof(uint32_t) * pixelsCount);
AndroidBitmap_unlockPixels(env, bitmap);
JniBitmap *jniBitmap = new JniBitmap();
jniBitmap->_bitmapInfo = bitmapInfo;
jniBitmap->_storedBitmapPixels = storedBitmapPixels;
return env->NewDirectByteBuffer(jniBitmap, 0);
}
src/com/jni/bitmap_operations/JniBitmapHolder.java
package com.jni.bitmap_operations;
import java.nio.ByteBuffer;
import android.graphics.Bitmap;
import android.util.Log;
public class JniBitmapHolder
{
ByteBuffer _handler =null;
static
{
System.loadLibrary("JniBitmapOperations");
}
private native ByteBuffer jniStoreBitmapData(Bitmap bitmap);
private native Bitmap jniGetBitmapFromStoredBitmapData(ByteBuffer handler);
private native void jniFreeBitmapData(ByteBuffer handler);
private native void jniRotateBitmapCcw90(ByteBuffer handler);
private native void jniCropBitmap(ByteBuffer handler,final int left,final int top,final int right,final int bottom);
public JniBitmapHolder()
{}
public JniBitmapHolder(final Bitmap bitmap)
{
storeBitmap(bitmap);
}
public void storeBitmap(final Bitmap bitmap)
{
if(_handler!=null)
freeBitmap();
_handler=jniStoreBitmapData(bitmap);
}
public void rotateBitmapCcw90()
{
if(_handler==null)
return;
jniRotateBitmapCcw90(_handler);
}
public void cropBitmap(final int left,final int top,final int right,final int bottom)
{
if(_handler==null)
return;
jniCropBitmap(_handler,left,top,right,bottom);
}
public Bitmap getBitmap()
{
if(_handler==null)
return null;
return jniGetBitmapFromStoredBitmapData(_handler);
}
public Bitmap getBitmapAndFree()
{
final Bitmap bitmap=getBitmap();
freeBitmap();
return bitmap;
}
public void freeBitmap()
{
if(_handler==null)
return;
jniFreeBitmapData(_handler);
_handler=null;
}
#Override
protected void finalize() throws Throwable
{
super.finalize();
if(_handler==null)
return;
Log.w("DEBUG","JNI bitmap wasn't freed nicely.please rememeber to free the bitmap as soon as you can");
freeBitmap();
}
}
I have an OpenCV Android app. Most of its code is in Java but I have
one function that is in C.
The function gets a Mat object and returns a new one.
My question is how do I return a Mat from the native code to Java?
Couldn't find any example of that.
Thanks.
Today I had to return a Mat from native code. I started with "Tutorial 2 Advanced - 2. Mix Java+Native OpenCV" it already passes two Mat (Images captured from camera) objects to the native code.
But I wanted to return extracted feature, thus I added jlong addrDescriptor to the signature:
extern "C" {
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_Sample4View_FindFeatures(JNIEnv* env, jobject thiz, jlong addrGray, jlong addrRgba, jlong addrDescriptor)
{
Mat* pMatGr=(Mat*)addrGray;
Mat* pMatRgb=(Mat*)addrRgba;
Mat* pMatDesc=(Mat*)addrDescriptor;
vector<KeyPoint> v;
//OrbFeatureDetector detector(50);
OrbFeatureDetector detector;
OrbDescriptorExtractor extractor;
detector.detect(*pMatGr, v);
extractor.compute( *pMatGr, v, *pMatDesc );
circle(*pMatRgb, Point(100,100), 10, Scalar(5,128,255,255));
for( size_t i = 0; i < v.size(); i++ ) {
circle(*pMatRgb, Point(v[i].pt.x, v[i].pt.y), 10, Scalar(255,128,0,255));
}
}
}
In the java part I added the Mat
private Mat descriptor;
descriptor = new Mat();
The method getNativeObjAddr() does the trick. The Mat is allocated in java and its address is passed to the native code, thus there isn't any explicit returning.
FindFeatures(mGraySubmat.getNativeObjAddr(), mRgba.getNativeObjAddr(), descriptor.getNativeObjAddr());
Log.i("desc:" , descriptor.dump());
The Mat was filled with the required data and is directly accessible in the java code after the JNI invokation returns.
Somwhere else in the code the Mat is released:
if ( descriptor != null)
descriptor.release();
descriptor = null;
in C++
jlong funC(){
Mat *mat = new Mat();
//...
return (jlong)mat;
}
in java:
long = addr;// addr is return from c method funC()
Mat mat = new Mat(addr);
Attention: You must new Mat() in C,if you code is : Mat mat();mat object memory will be collect when funC() end.