如何将向量列表(向量<point2f>)从JNI返回到Java?</point2f>

时间:2015-03-20 12:43:47

标签: android opencv android-ndk java-native-interface

我是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);

一切都适合我。我从本机代码Java代码返回int。我怀疑的是如何从原生代码向Java返回vector(我的方法中的'mc'对象)。请帮我找出从JNI返回向量列表的方法。

1 个答案:

答案 0 :(得分:3)

vector<Point2f>对应于Java中的MatOfPoint2f,它是Mat的派生类。

使用vectorMat转换功能,如在opencv repo(1)中

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