Ask Your Question
0

How to pass a MatOfKeyPoint and MatOfPoint2f to native code? (OpenCV 4 Android)

asked 2014-03-30 09:53:53 -0600

Isa gravatar image

updated 2014-03-30 13:27:27 -0600

berak gravatar image

I'm currently struggling with the Java Native Interface for Eclipse.

What I have:

With OpenCV, I detected keypoints of a frame and got back an object of type MatOfKeyPoint. (image is of type Mat)

private MatOfKeyPoint mKeypoints;
private FeatureDetector mDetector;
//(...)
mDetector = FeatureDetector.create(FeatureDetector.FAST);
mDetector.detect(image, mKeypoints);

What I want:

My mKeypoints is now of type MatOfKeyPoint. I want to pass this object to native code so I can do calculations faster. After my calculation, the native method should save its results in an object of type MatOfPoint2f

How I tried to do it:

I wrote a method

private native void getSkylinePoints(long addrMatOfKeyPoint, long addrOutputMat);

and used it like this:

getSkylinePoints(mKeypoints.getNativeObjAddr(), 
    mSkylinePoints.getNativeObjAddr());

(mSkylinePoints is of type MatOfPoint2f and is not null)

My c++ code then looks like this:

JNIEXPORT void JNICALL  
Java_ch_ethz_arskyline_detection_FASTDetector_getSkylinePoints(JNIEnv*, 
    jobject, jlong addrMatOfKeyPoint, jlong addrOutputMat)
{
    vector<KeyPoint>& keypoints  = *(vector<KeyPoint>*)addrMatOfKeyPoint;
    vector<Point2f>& output  = *(vector<Point2f>*)addrOutputMat;

        // without this line, it works
    if (!keypoints.empty())
        output.push_back (keypoints[0].pt);

}

I know that vector< KeyPoint> in c++ corresponds to MatOfKeyPoint in Java and vector< Point2f> in c++ corresponds to MatOfPoint2f in Java. I also wrote native functions that pass an object of type Mat (Mat in Java and Mat in c++) and there it works.

The error I get:

Debugging c++ code in eclipse is hard. All the LogCat tells me is:

Tag: libc   Text: fatal signal 6 (SIGABRT) at 0x000358a (code=-6), thread 13757 (Thread-5023)

I think that you can't just do this

vector<KeyPoint>& keypoints  = *(vector<KeyPoint>*)addrMatOfKeyPoint;

as I did with Mat objects:

Mat& background  = *(Mat*)addrBackground;

Does anyone know how to do this? Thanks in advance for any help!

Isa

edit retag flag offensive close merge delete

3 answers

Sort by » oldest newest most voted
1

answered 2014-03-31 03:48:43 -0600

Daniil Osokin gravatar image

updated 2014-03-31 04:23:54 -0600

Hi! MatOfKeyPoint just extends Mat (you can check implemetation in src/org/opencv/core/MatOfKeyPoint.java of your OpenCV android sdk). So, in native side, it just a Mat with CV_32FC7 type. Try to cast it to Mat in usual way.

edit flag offensive delete link more

Comments

1

Thanks! I casted it to Mat and then used Andreys answer to convert it to a vector of keypoints.

Isa gravatar imageIsa ( 2014-03-31 12:00:38 -0600 )edit
2

answered 2014-03-31 11:03:37 -0600

Andrey Pavlenko gravatar image
// C++ / JNI
// vector_KeyPoint converters

void Mat_to_vector_KeyPoint(Mat& mat, vector<KeyPoint>& v_kp)
{
    v_kp.clear();
    CHECK_MAT(mat.type()==CV_32FC(7) && mat.cols==1);
    for(int i=0; i<mat.rows; i++)
    {
        Vec<float, 7> v = mat.at< Vec<float, 7> >(i, 0);
        KeyPoint kp(v[0], v[1], v[2], v[3], v[4], (int)v[5], (int)v[6]);
        v_kp.push_back(kp);
    }
    return;
}


void vector_KeyPoint_to_Mat(vector<KeyPoint>& v_kp, Mat& mat)
{
    int count = (int)v_kp.size();
    mat.create(count, 1, CV_32FC(7));
    for(int i=0; i<count; i++)
    {
        KeyPoint kp = v_kp[i];
        mat.at< Vec<float, 7> >(i, 0) = Vec<float, 7>(kp.pt.x, kp.pt.y, kp.size, kp.angle, kp.response, (float)kp.octave, (float)kp.class_id);
    }
}
edit flag offensive delete link more

Comments

Nice to see you here!

Daniil Osokin gravatar imageDaniil Osokin ( 2014-03-31 14:30:57 -0600 )edit
1

answered 2014-03-31 11:06:56 -0600

Andrey Pavlenko gravatar image
//C++/JNI
//vector_Point2f

void Mat_to_vector_Point2f(Mat& mat, vector<Point2f>& v_point)
{
    v_point.clear();
    CHECK_MAT(mat.type()==CV_32FC2 && mat.cols==1);
    v_point = (vector<Point2f>) mat;
}

void vector_Point2f_to_Mat(vector<Point2f>& v_point, Mat& mat)
{
    mat = Mat(v_point, true);
}
edit flag offensive delete link more

Comments

Hello, I'm having a hell of a time trying to get this to work. When I try Mat_to_vector_Point2f I get the following error in my log file (Android)

error()﹕ OpenCV Error: Assertion failed (channels() == CV_MAT_CN(dtype)) in void cv::Mat::copyTo(cv::OutputArray) const, file /home/reports/ci/slave_desktop/50-SDK/opencv/modules/core/src/copy.cpp, line 212

Here's my code that sets up the call:

vector&lt;cv::Point2f&gt; points1, points2;
cv::Mat&amp; previousMatPoints = *(cv::Mat *)addrInputPointsVector;
cv::Mat&amp; nextMatPoints = *(cv::Mat *)addrOutputPointsVector;
Mat_to_vector_Point2f(previousMatPoints, points1);
Mat_to_vector_Point2f(nextMatPoints, points2);

I'm totally stumped. The Java code passes in the long values generated from the .getNativeObjAddr() calls

valder gravatar imagevalder ( 2014-08-22 13:47:48 -0600 )edit

Question Tools

Stats

Asked: 2014-03-30 09:53:53 -0600

Seen: 3,468 times

Last updated: Mar 31 '14