From fb68223b5cf575d38f51f8191c2e0df5b6d26283 Mon Sep 17 00:00:00 2001 From: utibenkei Date: Sun, 27 Jul 2025 22:39:02 +0900 Subject: [PATCH] Add Java wrapper support for List> - Added vector_vector_Mat to gen_dict.json - Implemented Mat_to_vector_vector_Mat and vector_vector_Mat_to_Mat conversion functions in converters.h/cpp and Converters.java - Added DnnForwardAndRetrieve.java test to verify List> conversion : Reference: C++ test in modules/dnn/test/test_misc.cpp - TEST(Net, forwardAndRetrieve) --- modules/core/misc/java/gen_dict.json | 9 +++ .../misc/java/test/DnnForwardAndRetrieve.java | 66 +++++++++++++++++++ modules/java/generator/src/cpp/converters.cpp | 26 ++++++++ modules/java/generator/src/cpp/converters.h | 3 + .../src/java/org/opencv/utils/Converters.java | 35 ++++++++++ 5 files changed, 139 insertions(+) create mode 100644 modules/dnn/misc/java/test/DnnForwardAndRetrieve.java diff --git a/modules/core/misc/java/gen_dict.json b/modules/core/misc/java/gen_dict.json index 924318c30e..c6aaa2ef92 100644 --- a/modules/core/misc/java/gen_dict.json +++ b/modules/core/misc/java/gen_dict.json @@ -877,6 +877,15 @@ "v_type": "Mat", "j_import": "org.opencv.core.MatOfByte" }, + "vector_vector_Mat": { + "j_type": "List>", + "jn_type": "long", + "jni_type": "jlong", + "jni_var": "std::vector< std::vector > %(n)s", + "suffix": "J", + "v_type": "vector_Mat", + "j_import": "org.opencv.core.Mat" + }, "vector_vector_DMatch": { "j_type": "List", "jn_type": "long", diff --git a/modules/dnn/misc/java/test/DnnForwardAndRetrieve.java b/modules/dnn/misc/java/test/DnnForwardAndRetrieve.java new file mode 100644 index 0000000000..6a4fd771b3 --- /dev/null +++ b/modules/dnn/misc/java/test/DnnForwardAndRetrieve.java @@ -0,0 +1,66 @@ +package org.opencv.test.dnn; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Core; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.MatOfByte; +import org.opencv.core.Range; +import org.opencv.dnn.Dnn; +import org.opencv.dnn.Net; +import org.opencv.test.OpenCVTestCase; + +public class DnnForwardAndRetrieve extends OpenCVTestCase { + + public void testForwardAndRetrieve() + { + // Create a simple Caffe prototxt with a Slice layer + String prototxt = + "input: \"data\"\n" + + "layer {\n" + + " name: \"testLayer\"\n" + + " type: \"Slice\"\n" + + " bottom: \"data\"\n" + + " top: \"firstCopy\"\n" + + " top: \"secondCopy\"\n" + + " slice_param {\n" + + " axis: 0\n" + + " slice_point: 2\n" + + " }\n" + + "}"; + + // Read network from prototxt + MatOfByte bufferProto = new MatOfByte(); + bufferProto.fromArray(prototxt.getBytes()); + Net net = Dnn.readNetFromCaffe(bufferProto); + net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV); + + // Create input data + Mat inp = new Mat(4, 5, CvType.CV_32F); + Core.randu(inp, -1, 1); + net.setInput(inp); + + // Define output names + List outNames = new ArrayList<>(); + outNames.add("testLayer"); + + // Forward and retrieve multiple outputs + List> outBlobs = new ArrayList<>(); + net.forwardAndRetrieve(outBlobs, outNames); + + // Verify results + assertEquals(1, outBlobs.size()); + assertEquals(2, outBlobs.get(0).size()); + + // Compare results + Mat expectedFirst = inp.rowRange(0, 2); + Mat expectedSecond = inp.rowRange(2, 4); + + Mat actualFirst = outBlobs.get(0).get(0); + Mat actualSecond = outBlobs.get(0).get(1); + + assertEquals(0, Core.norm(expectedFirst, actualFirst, Core.NORM_INF), EPS); + assertEquals(0, Core.norm(expectedSecond, actualSecond, Core.NORM_INF), EPS); + } +} diff --git a/modules/java/generator/src/cpp/converters.cpp b/modules/java/generator/src/cpp/converters.cpp index 9c4caaccca..60aff1e2eb 100644 --- a/modules/java/generator/src/cpp/converters.cpp +++ b/modules/java/generator/src/cpp/converters.cpp @@ -232,6 +232,32 @@ void vector_Mat_to_Mat(std::vector& v_mat, cv::Mat& mat) } } +void Mat_to_vector_vector_Mat(Mat& mat, std::vector< std::vector< Mat > >& vv_mat) +{ + std::vector vm; + vm.reserve( mat.rows ); + Mat_to_vector_Mat(mat, vm); + for(size_t i=0; i vmat; + Mat_to_vector_Mat(vm[i], vmat); + vv_mat.push_back(vmat); + } +} + +void vector_vector_Mat_to_Mat(std::vector< std::vector< Mat > >& vv_mat, Mat& mat) +{ + std::vector vm; + vm.reserve( vv_mat.size() ); + for(size_t i=0; i >& vv_pt) { std::vector vm; diff --git a/modules/java/generator/src/cpp/converters.h b/modules/java/generator/src/cpp/converters.h index 019d7d698f..bb82276446 100644 --- a/modules/java/generator/src/cpp/converters.h +++ b/modules/java/generator/src/cpp/converters.h @@ -50,6 +50,9 @@ void vector_Vec6f_to_Mat(std::vector& v_vec, cv::Mat& mat); void Mat_to_vector_Mat(cv::Mat& mat, std::vector& v_mat); void vector_Mat_to_Mat(std::vector& v_mat, cv::Mat& mat); +void Mat_to_vector_vector_Mat(cv::Mat& mat, std::vector< std::vector< cv::Mat > >& vv_mat); +void vector_vector_Mat_to_Mat(std::vector< std::vector< cv::Mat > >& vv_mat, cv::Mat& mat); + void Mat_to_vector_vector_char(cv::Mat& mat, std::vector< std::vector< char > >& vv_ch); void vector_vector_char_to_Mat(std::vector< std::vector< char > >& vv_ch, cv::Mat& mat); diff --git a/modules/java/generator/src/java/org/opencv/utils/Converters.java b/modules/java/generator/src/java/org/opencv/utils/Converters.java index 35beecbc4b..146ed70256 100644 --- a/modules/java/generator/src/java/org/opencv/utils/Converters.java +++ b/modules/java/generator/src/java/org/opencv/utils/Converters.java @@ -514,6 +514,41 @@ public class Converters { } } + // vector_vector_Mat + public static Mat vector_vector_Mat_to_Mat(List> vecMats, List mats) { + Mat res; + int lCount = (vecMats != null) ? vecMats.size() : 0; + if (lCount > 0) { + for (List matList : vecMats) { + Mat mat = vector_Mat_to_Mat(matList); + mats.add(mat); + } + res = vector_Mat_to_Mat(mats); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_vector_Mat(Mat m, List> vecMats) { + if (vecMats == null) + throw new IllegalArgumentException("Output List can't be null"); + + if (m == null) + throw new IllegalArgumentException("Input Mat can't be null"); + + vecMats.clear(); + List mats = new ArrayList(m.rows()); + Mat_to_vector_Mat(m, mats); + for (Mat mi : mats) { + List rowList = new ArrayList(mi.rows()); + Mat_to_vector_Mat(mi, rowList); + vecMats.add(rowList); + mi.release(); + } + mats.clear(); + } + // vector_vector_Point public static Mat vector_vector_Point_to_Mat(List pts, List mats) { Mat res;