Почему findContour не работает правильно при использовании камеры телефона? - PullRequest
0 голосов
/ 29 января 2019

Я написал функцию jni для определения угловых точек исходного изображения с помощью функции findContour, а затем с помощью возвращенного массива точек извлекаю самый большой контур с помощью функции warpPerspective.Все отлично работает при использовании исходного изображения из папки drawable, но проблема в том, что когда я использую тот же алгоритм внутри метода onCameraFrame, он дает мне странные черные изображения

вот код, который я написал:

Функция jni:

    extern "C" jobjectArray
    Java_com_grimg_testtt_Main2Activity_getQuadrilateral(
    JNIEnv *env,
    jobject /* this */,
    jlong image) {
    std::vector<std::string> vec;
    cv::Mat* frame = (cv::Mat*) image;
    cv::Mat approxPoly_mask(frame->rows, frame->cols, CV_8UC1);
    approxPoly_mask = cv::Scalar(0);
    std::vector<std::vector<cv::Point>> contours;
    findContours(*frame, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
std::vector<int> indices(contours.size());
std::iota(indices.begin(), indices.end(), 0);
sort(indices.begin(), indices.end(), [&contours](int lhs, int rhs) {
    return contours[lhs].size() > contours[rhs].size();
});
/// Find the convex hull object for each contour
std::vector<std::vector<cv::Point>> hull(1);
cv::convexHull(cv::Mat(contours[indices[0]]), hull[0], false);

std::vector<std::vector<cv::Point>> polygon(1);
approxPolyDP(hull[0], polygon[0], 20, true);
drawContours(approxPoly_mask, polygon, 0, cv::Scalar(255));


jobjectArray ret;
ret= (jobjectArray)env->NewObjectArray(polygon[0].size(),env->FindClass("java/lang/String"),env->NewStringUTF(""));
// if (polygon[0].size() >= 4) // we found the 4 corners
//{
for (int n=0;n<polygon[0].size();n++) {
    std::string point_str = std::to_string(polygon[0][n].x) + "," + std::to_string(polygon[0][n].y);
    env->SetObjectArrayElement(ret,n,env->NewStringUTF(point_str.c_str()));
}
//  }
return (ret);

}

Функция извлечения java:

     private Mat detect_and_extract_largest_contour(Mat source_mat) {
    double ratio = source_mat.size().height / 500;
    int height = Double.valueOf(source_mat.size().height / ratio).intValue();
    int width = Double.valueOf(source_mat.size().width / ratio).intValue();
    Size size = new Size(width,height);


    Mat input_grey = new Mat(size, CvType.CV_8UC4);

    Imgproc.cvtColor(source_mat, input_grey, Imgproc.COLOR_RGB2GRAY);
    Mat threshold1;
    Mat edges = new Mat();
    Imgproc.GaussianBlur(input_grey, input_grey, new Size(3, 3), 3);
    Imgproc.Canny(input_grey, edges, 50, 150, 3, false);

    cppArray = getQuadrilateral(edges.getNativeObjAddr());

    card_corners = new ArrayList<>();
    for (int i =0; i<cppArray.length; i++) {
        String[] separated = cppArray[i].split(",");
        pt = new Point();
        pt.x = Double.parseDouble(separated[0]);
        pt.y = Double.parseDouble(separated[1]);
        card_corners.add(pt);
    }

    Mat warpedCard=  new Mat(source_mat.rows(), source_mat.cols(), CvType.CV_8UC3);

    if (card_corners.size() == 4)
    {
        final Point p1 = new Point(warpedCard.cols(), warpedCard.rows());
        final Point p2 = new Point(0, warpedCard.rows());
        final Point p3 = new Point(0, 0);
        final Point p4 = new Point(warpedCard.cols(), 0);

        LinkedList<Point> sceneList = new LinkedList<Point>();
        sceneList.addLast(p1);
        sceneList.addLast(p2);
        sceneList.addLast(p3);
        sceneList.addLast(p4);

        MatOfPoint2f scene = new MatOfPoint2f();
        scene.fromList(sceneList);

        MatOfPoint2f obj = new MatOfPoint2f();
        obj.fromList(card_corners);

        Mat homography = Calib3d.findHomography(obj, scene);
        Imgproc.warpPerspective(input_grey, warpedCard, homography, new Size(warpedCard.cols(), warpedCard.rows()));
    }

    return warpedCard;
}

код onCameraFrame:

    mat = inputFrame.rgba();
    Mat mRgbaT = mat.t();
    Core.flip(mat.t(), mRgbaT, 1);
    Imgproc.resize(mRgbaT, mRgbaT, mat.size());

    return detect_and_extract_largest_contour(mRgbaT);

Что не так?Как сделать результат точным, даже когда я использую камеру?

Заранее спасибо.

...