如何从 JNI return 向量列表 (vector<Point2f>) 到 Java?

How to return vectors lists (vector<Point2f>) from JNI to Java?

我是Android+OpenCV+JNI开发新手。我试图找出最大的轮廓 这是我的本机代码:

JNIEXPORT jint JNICALL 
    Java_org_opencv_samples_tutorial3_Sample3Native_FindSquares
    (JNIEnv* env, jobject, jlong addrRgba, jint draw) {

    Mat& image = *(Mat*) addrRgba;
    int thresh = 50, N = 4;
    int found = 0;
    Mat pyr, timg, gray0(image.size(), CV_8U), gray;
    pyrDown(image, pyr, Size(image.cols / 2, image.rows / 2));
    pyrUp(pyr, timg, image.size());
    vector < vector<Point> > contours;

    // find squares in every color plane of the image
    for (int c = 1; c < 3; c++) {
        int ch[] = { c, 0 };
        mixChannels(&timg, 1, &gray0, 1, ch, 1);
        // try several threshold levels
        for (int l = 0; l < N; l++) {
            // hack: use Canny instead of zero threshold level.
            // Canny helps to catch squares with gradient shading
            if (l == 0) {
                // apply Canny. Take the upper threshold from slider
                // and set the lower to 0 (which forces edges merging)
                Canny(gray0, gray, 0, thresh, 5);
                // dilate canny output to remove potential
                // holes between edge segments
                dilate(gray, gray, Mat(), Point(-1, -1));
            } else {
                // apply threshold if l!=0:
                //     tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
                gray = gray0 >= (l + 1) * 255 / N;
            }

            // find contours and store them all as a list
            findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
            vector<Point> approx;
            // test each contour
            for (size_t i = 0; i < contours.size(); i++) {

                // approximate contour with accuracy proportional
                // to the contour perimeter
                approxPolyDP(Mat(contours[i]), approx,
                        arcLength(Mat(contours[i]), true) * 0.02, true);

                // square contours should have 4 vertices after approximation
                // relatively large area (to filter out noisy contours)
                // and be convex.
                // Note: absolute value of an area is used because
                // area may be positive or negative - in accordance with the
                // contour orientation
                if (approx.size() == 4 && fabs(contourArea(Mat(approx))) > 1000
                        && isContourConvex(Mat(approx))) {
                    double maxCosine = 0;

                    for (int j = 2; j < 5; j++) {
                        // find the maximum cosine of the angle between joint edges
                        double cosine = fabs(
                                angle(approx[j % 4], approx[j - 2],
                                        approx[j - 1]));
                        maxCosine = MAX(maxCosine, cosine);
                    }

                    // if cosines of all angles are small
                    // (all angles are ~90 degree) then write quandrange
                    // vertices to resultant sequence
                    if (maxCosine < 0.3) {

                        circle(image, approx[0], 5, Scalar(255, 0, 0, 255), 3,
                                4, 0);
                        circle(image, approx[1], 5, Scalar(255, 0, 0, 255), 3,
                                4, 0);
                        circle(image, approx[2], 5, Scalar(255, 0, 0, 255), 3,
                                4, 0);
                        circle(image, approx[3], 5, Scalar(255, 0, 0, 255), 3,
                                4, 0);
                        //rectangle(image, approx[0], approx[2], Scalar(0,255,0,255), 5, 4, 0);

                        //Center of this rectangle
                        int x = (int) ((approx[0].x + approx[1].x + approx[2].x
                                + approx[3].x) / 4.0);
                        int y = (int) ((approx[0].y + approx[1].y + approx[2].y
                                + approx[3].y) / 4.0);

                        if ((int) draw) {
                            //outline
                            line(image, approx[0], approx[1],
                                    Scalar(0, 255, 0, 255), 1, 4, 0);
                            line(image, approx[1], approx[2],
                                    Scalar(0, 255, 0, 255), 1, 4, 0);
                            line(image, approx[2], approx[3],
                                    Scalar(0, 255, 0, 255), 1, 4, 0);
                            line(image, approx[3], approx[0],
                                    Scalar(0, 255, 0, 255), 1, 4, 0);
                        }
                        /// Get the moments
                        vector<Moments> mu(contours.size());
                        for (int i = 0; i < contours.size(); i++) {
                            mu[i] = moments(contours[i], false);
                        }

                        ///  Get the mass centers:
                        vector<Point2f> mc(contours.size());

                        for (int i = 0; i < contours.size(); i++) {
                            mc[i] = Point2f(mu[i].m10 / mu[i].m00,
                                    mu[i].m01 / mu[i].m00);
                        }
                        /// Draw contours
                        for (int i = 0; i < contours.size(); i++) {
                            circle(image, mc[i], 10, Scalar(255, 0, 0), 1,
                                    CV_AA, 0);

                        }

                        found = 1;
                        jint result = (jint) found;
                        return result;
                    }
                }
            }
        }
    }
    jint result = (jint) found;
    return result;
}

还有我 我从 java 代码中调用此本机方法为

public native void FindFeatures(long matAddrGr, long matAddrRgba);

对我来说一切正常。我正在 returning 来自本机代码 Java 代码的 int。我的疑问是我如何 return 向量(在我的方法中是 'mc' 对象)从本机代码到 Java。请帮我找出从 JNI 到 Java.

的 return 向量列表的方法

vector<Point2f> 对应于 Java 中的 MatOfPoint2f,它是 Mat.

的派生 class

使用 vectorMat 的转换函数,如 opencv repo(1)

void vector_Point2f_to_Mat(vector<Point2f>& v_point, Mat& mat)
{
    mat = Mat(v_point, true);
}