From: Giles Payne Date: Sat, 9 Mar 2019 21:11:04 +0000 (+0900) Subject: Merge pull request #13956 from komakai:java-mat-class-improvements X-Git-Tag: accepted/tizen/6.0/unified/20201030.111113~1^2~306^2~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=11dbd86aa3fa70c9a28f14203edc65b0f7f68273;p=platform%2Fupstream%2Fopencv.git Merge pull request #13956 from komakai:java-mat-class-improvements * Expose more C++ functionality in the Java wrapper of the Mat class In particular expose methods for handling Mat with more than 2 dimensions * add constructors taking an array of dimension sizes * add constructor taking an existing Mat and an array of Ranges * add override of the create method taking an array of dimension sizes * add overrides of the ones and zeros methods taking an array of dimension sizes * add override of the submat method taking an array of ranges * add overrides of put and get taking arrays of indices * add wrapper for copySize method * fix crash in the JNI wrapper of the reshape(int cn, int[] newshape) method * add test for each method added to Mat.java * Fix broken test --- diff --git a/modules/core/misc/java/src/java/core+Mat.java b/modules/core/misc/java/src/java/core+Mat.java index c75f9d5..e42fca9 100644 --- a/modules/core/misc/java/src/java/core+Mat.java +++ b/modules/core/misc/java/src/java/core+Mat.java @@ -68,6 +68,19 @@ public class Mat { } // + // C++: Mat::Mat(int ndims, const int* sizes, int type) + // + + // javadoc: Mat::Mat(sizes, type) + public Mat(int[] sizes, int type) + { + + nativeObj = n_Mat(sizes.length, sizes, type); + + return; + } + + // // C++: Mat::Mat(int rows, int cols, int type, Scalar s) // @@ -94,6 +107,19 @@ public class Mat { } // + // C++: Mat::Mat(int ndims, const int* sizes, int type, Scalar s) + // + + // javadoc: Mat::Mat(sizes, type, s) + public Mat(int[] sizes, int type, Scalar s) + { + + nativeObj = n_Mat(sizes.length, sizes, type, s.val[0], s.val[1], s.val[2], s.val[3]); + + return; + } + + // // C++: Mat::Mat(Mat m, Range rowRange, Range colRange = Range::all()) // @@ -116,6 +142,19 @@ public class Mat { } // + // C++: Mat::Mat(const Mat& m, const std::vector& ranges) + // + + // javadoc: Mat::Mat(m, ranges) + public Mat(Mat m, Range[] ranges) + { + + nativeObj = n_Mat(m.nativeObj, ranges); + + return; + } + + // // C++: Mat::Mat(Mat m, Rect roi) // @@ -371,6 +410,31 @@ public class Mat { } // + // C++: void Mat::create(int ndims, const int* sizes, int type) + // + + // javadoc: Mat::create(sizes, type) + public void create(int[] sizes, int type) + { + + n_create(nativeObj, sizes.length, sizes, type); + + return; + } + + // + // C++: void Mat::copySize(const Mat& m); + // + + // javadoc: Mat::copySize(m) + public void copySize(Mat m) + { + n_copySize(nativeObj, m.nativeObj); + + return; + } + + // // C++: Mat Mat::cross(Mat m) // @@ -634,6 +698,19 @@ public class Mat { } // + // C++: static Mat Mat::ones(int ndims, const int* sizes, int type) + // + + // javadoc: Mat::ones(sizes, type) + public static Mat ones(int[] sizes, int type) + { + + Mat retVal = new Mat(n_ones(sizes.length, sizes, type)); + + return retVal; + } + + // // C++: void Mat::push_back(Mat m) // @@ -868,6 +945,19 @@ public class Mat { } // + // C++: Mat Mat::operator()(const std::vector& ranges) + // + + // javadoc: Mat::operator()(ranges[]) + public Mat submat(Range[] ranges) + { + + Mat retVal = new Mat(n_submat_ranges(nativeObj, ranges)); + + return retVal; + } + + // // C++: Mat Mat::operator()(Rect roi) // @@ -945,6 +1035,19 @@ public class Mat { return retVal; } + // + // C++: static Mat Mat::zeros(int ndims, const int* sizes, int type) + // + + // javadoc: Mat::zeros(sizes, type) + public static Mat zeros(int[] sizes, int type) + { + + Mat retVal = new Mat(n_zeros(sizes.length, sizes, type)); + + return retVal; + } + @Override protected void finalize() throws Throwable { n_delete(nativeObj); @@ -979,6 +1082,20 @@ public class Mat { return nPutD(nativeObj, row, col, data.length, data); } + // javadoc:Mat::put(idx,data) + public int put(int[] idx, double... data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new java.lang.UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + return nPutDIdx(nativeObj, idx, data.length, data); + } + // javadoc:Mat::put(row,col,data) public int put(int row, int col, float[] data) { int t = type(); @@ -994,6 +1111,23 @@ public class Mat { throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); } + // javadoc:Mat::put(idx,data) + public int put(int[] idx, float[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new java.lang.UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_32F) { + return nPutFIdx(nativeObj, idx, data.length, data); + } + throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); + } + // javadoc:Mat::put(row,col,data) public int put(int row, int col, int[] data) { int t = type(); @@ -1009,6 +1143,23 @@ public class Mat { throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); } + // javadoc:Mat::put(idx,data) + public int put(int[] idx, int[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new java.lang.UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_32S) { + return nPutIIdx(nativeObj, idx, data.length, data); + } + throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); + } + // javadoc:Mat::put(row,col,data) public int put(int row, int col, short[] data) { int t = type(); @@ -1024,6 +1175,23 @@ public class Mat { throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); } + // javadoc:Mat::put(idx,data) + public int put(int[] idx, short[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new java.lang.UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_16U || CvType.depth(t) == CvType.CV_16S) { + return nPutSIdx(nativeObj, idx, data.length, data); + } + throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); + } + // javadoc:Mat::put(row,col,data) public int put(int row, int col, byte[] data) { int t = type(); @@ -1039,6 +1207,23 @@ public class Mat { throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); } + // javadoc:Mat::put(idx,data) + public int put(int[] idx, byte[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new java.lang.UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_8U || CvType.depth(t) == CvType.CV_8S) { + return nPutBIdx(nativeObj, idx, data.length, data); + } + throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); + } + // javadoc:Mat::put(row,col,data,offset,length) public int put(int row, int col, byte[] data, int offset, int length) { int t = type(); @@ -1054,6 +1239,23 @@ public class Mat { throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); } + // javadoc:Mat::put(idx,data,offset,length) + public int put(int[] idx, byte[] data, int offset, int length) { + int t = type(); + if (data == null || length % CvType.channels(t) != 0) + throw new java.lang.UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_8U || CvType.depth(t) == CvType.CV_8S) { + return nPutBwIdxOffset(nativeObj, idx, length, offset, data); + } + throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); + } + // javadoc:Mat::get(row,col,data) public int get(int row, int col, byte[] data) { int t = type(); @@ -1069,6 +1271,23 @@ public class Mat { throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); } + // javadoc:Mat::get(idx,data) + public int get(int[] idx, byte[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new java.lang.UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_8U || CvType.depth(t) == CvType.CV_8S) { + return nGetBIdx(nativeObj, idx, data.length, data); + } + throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); + } + // javadoc:Mat::get(row,col,data) public int get(int row, int col, short[] data) { int t = type(); @@ -1084,6 +1303,23 @@ public class Mat { throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); } + // javadoc:Mat::get(idx,data) + public int get(int[] idx, short[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new java.lang.UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_16U || CvType.depth(t) == CvType.CV_16S) { + return nGetSIdx(nativeObj, idx, data.length, data); + } + throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); + } + // javadoc:Mat::get(row,col,data) public int get(int row, int col, int[] data) { int t = type(); @@ -1099,6 +1335,23 @@ public class Mat { throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); } + // javadoc:Mat::get(idx,data) + public int get(int[] idx, int[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new java.lang.UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_32S) { + return nGetIIdx(nativeObj, idx, data.length, data); + } + throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); + } + // javadoc:Mat::get(row,col,data) public int get(int row, int col, float[] data) { int t = type(); @@ -1114,6 +1367,23 @@ public class Mat { throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); } + // javadoc:Mat::get(idx,data) + public int get(int[] idx, float[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new java.lang.UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_32F) { + return nGetFIdx(nativeObj, idx, data.length, data); + } + throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); + } + // javadoc:Mat::get(row,col,data) public int get(int row, int col, double[] data) { int t = type(); @@ -1129,11 +1399,35 @@ public class Mat { throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); } + // javadoc:Mat::get(idx,data) + public int get(int[] idx, double[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new java.lang.UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_64F) { + return nGetDIdx(nativeObj, idx, data.length, data); + } + throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); + } + // javadoc:Mat::get(row,col) public double[] get(int row, int col) { return nGet(nativeObj, row, col); } + // javadoc:Mat::get(idx) + public double[] get(int[] idx) { + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + return nGetIdx(nativeObj, idx); + } + // javadoc:Mat::height() public int height() { return rows(); @@ -1155,6 +1449,9 @@ public class Mat { // C++: Mat::Mat(int rows, int cols, int type) private static native long n_Mat(int rows, int cols, int type); + // C++: Mat::Mat(int ndims, const int* sizes, int type) + private static native long n_Mat(int ndims, int[] sizes, int type); + // C++: Mat::Mat(int rows, int cols, int type, void* data) private static native long n_Mat(int rows, int cols, int type, ByteBuffer data); @@ -1167,11 +1464,17 @@ public class Mat { // C++: Mat::Mat(Size size, int type, Scalar s) private static native long n_Mat(double size_width, double size_height, int type, double s_val0, double s_val1, double s_val2, double s_val3); + // C++: Mat::Mat(int ndims, const int* sizes, int type, Scalar s) + private static native long n_Mat(int ndims, int[] sizes, int type, double s_val0, double s_val1, double s_val2, double s_val3); + // C++: Mat::Mat(Mat m, Range rowRange, Range colRange = Range::all()) private static native long n_Mat(long m_nativeObj, int rowRange_start, int rowRange_end, int colRange_start, int colRange_end); private static native long n_Mat(long m_nativeObj, int rowRange_start, int rowRange_end); + // C++: Mat::Mat(const Mat& m, const std::vector& ranges) + private static native long n_Mat(long m_nativeObj, Range[] ranges); + // C++: Mat Mat::adjustROI(int dtop, int dbottom, int dleft, int dright) private static native long n_adjustROI(long nativeObj, int dtop, int dbottom, int dleft, int dright); @@ -1226,6 +1529,12 @@ public class Mat { // C++: void Mat::create(Size size, int type) private static native void n_create(long nativeObj, double size_width, double size_height, int type); + // C++: void Mat::create(int ndims, const int* sizes, int type) + private static native void n_create(long nativeObj, int ndims, int[] sizes, int type); + + // C++: void Mat::copySize(const Mat& m) + private static native void n_copySize(long nativeObj, long m_nativeObj); + // C++: Mat Mat::cross(Mat m) private static native long n_cross(long nativeObj, long m_nativeObj); @@ -1284,6 +1593,9 @@ public class Mat { // C++: static Mat Mat::ones(Size size, int type) private static native long n_ones(double size_width, double size_height, int type); + // C++: static Mat Mat::ones(int ndims, const int* sizes, int type) + private static native long n_ones(int ndims, int[] sizes, int type); + // C++: void Mat::push_back(Mat m) private static native void n_push_back(long nativeObj, long m_nativeObj); @@ -1332,6 +1644,9 @@ public class Mat { // C++: Mat Mat::operator()(Range rowRange, Range colRange) private static native long n_submat_rr(long nativeObj, int rowRange_start, int rowRange_end, int colRange_start, int colRange_end); + // C++: Mat Mat::operator()(const std::vector& ranges) + private static native long n_submat_ranges(long nativeObj, Range[] ranges); + // C++: Mat Mat::operator()(Rect roi) private static native long n_submat(long nativeObj, int roi_x, int roi_y, int roi_width, int roi_height); @@ -1350,32 +1665,59 @@ public class Mat { // C++: static Mat Mat::zeros(Size size, int type) private static native long n_zeros(double size_width, double size_height, int type); + // C++: static Mat Mat::zeros(int ndims, const int* sizes, int type) + private static native long n_zeros(int ndims, int[] sizes, int type); + // native support for java finalize() private static native void n_delete(long nativeObj); private static native int nPutD(long self, int row, int col, int count, double[] data); + private static native int nPutDIdx(long self, int[] idx, int count, double[] data); + private static native int nPutF(long self, int row, int col, int count, float[] data); + private static native int nPutFIdx(long self, int[] idx, int count, float[] data); + private static native int nPutI(long self, int row, int col, int count, int[] data); + private static native int nPutIIdx(long self, int[] idx, int count, int[] data); + private static native int nPutS(long self, int row, int col, int count, short[] data); + private static native int nPutSIdx(long self, int[] idx, int count, short[] data); + private static native int nPutB(long self, int row, int col, int count, byte[] data); + private static native int nPutBIdx(long self, int[] idx, int count, byte[] data); + private static native int nPutBwOffset(long self, int row, int col, int count, int offset, byte[] data); + private static native int nPutBwIdxOffset(long self, int[] idx, int count, int offset, byte[] data); + private static native int nGetB(long self, int row, int col, int count, byte[] vals); + private static native int nGetBIdx(long self, int[] idx, int count, byte[] vals); + private static native int nGetS(long self, int row, int col, int count, short[] vals); + private static native int nGetSIdx(long self, int[] idx, int count, short[] vals); + private static native int nGetI(long self, int row, int col, int count, int[] vals); + private static native int nGetIIdx(long self, int[] idx, int count, int[] vals); + private static native int nGetF(long self, int row, int col, int count, float[] vals); + private static native int nGetFIdx(long self, int[] idx, int count, float[] vals); + private static native int nGetD(long self, int row, int col, int count, double[] vals); + private static native int nGetDIdx(long self, int[] idx, int count, double[] vals); + private static native double[] nGet(long self, int row, int col); + private static native double[] nGetIdx(long self, int[] idx); + private static native String nDump(long self); } diff --git a/modules/core/misc/java/test/MatTest.java b/modules/core/misc/java/test/MatTest.java index f0f4fdc..4c8c52b 100644 --- a/modules/core/misc/java/test/MatTest.java +++ b/modules/core/misc/java/test/MatTest.java @@ -185,6 +185,16 @@ public class MatTest extends OpenCVTestCase { assertEquals(CvType.CV_16U, dst.type()); } + public void testCreateIntArrayInt() { + int[] dims = new int[] {5, 6, 7}; + dst.create(dims, CvType.CV_16U); + + assertEquals(5, dst.size(0)); + assertEquals(6, dst.size(1)); + assertEquals(7, dst.size(2)); + assertEquals(CvType.CV_16U, dst.type()); + } + public void testCross() { Mat answer = new Mat(1, 3, CvType.CV_32F); answer.put(0, 0, 7.0, 1.0, -5.0); @@ -569,6 +579,15 @@ public class MatTest extends OpenCVTestCase { assertMatEqual(truth, dst, EPS); } + public void testMatMatRangeArray() { + dst = new Mat(gray255_32f_3d, new Range[]{new Range(0, 5), new Range(0, 5), new Range(0, 5)}); + + truth = new Mat(new int[] {5, 5, 5}, CvType.CV_32FC1, new Scalar(255)); + + assertFalse(dst.empty()); + assertMatEqual(truth, dst, EPS); + } + public void testMatMatRect() { Mat m = new Mat(7, 6, CvType.CV_32SC1); m.put(0, 0, @@ -606,6 +625,13 @@ public class MatTest extends OpenCVTestCase { assertMatEqual(gray255_32f, dst, EPS); } + public void testMatIntArrayIntScalar() { + dst = new Mat(new int[]{10, 10, 10}, CvType.CV_32F, new Scalar(255)); + + assertFalse(dst.empty()); + assertMatEqual(gray255_32f_3d, dst, EPS); + } + public void testMulMat() { assertMatEqual(gray0, gray0.mul(gray255)); @@ -619,6 +645,16 @@ public class MatTest extends OpenCVTestCase { } + public void testMulMat3d() { + Mat m1 = new Mat(new int[] {2, 2, 2}, CvType.CV_32F, new Scalar(2)); + Mat m2 = new Mat(new int[] {2, 2, 2}, CvType.CV_32F, new Scalar(3)); + + dst = m1.mul(m2); + + truth = new Mat(new int[] {2, 2, 2}, CvType.CV_32F, new Scalar(6)); + assertMatEqual(truth, dst, EPS); + } + public void testMulMatDouble() { Mat m1 = new Mat(2, 2, CvType.CV_32F, new Scalar(2)); Mat m2 = new Mat(2, 2, CvType.CV_32F, new Scalar(3)); @@ -642,6 +678,12 @@ public class MatTest extends OpenCVTestCase { assertMatEqual(truth, dst); } + public void testOnesIntArrayInt() { + dst = Mat.ones(new int[]{2, 2, 2}, CvType.CV_16S); + truth = new Mat(new int[]{2, 2, 2}, CvType.CV_16S, new Scalar(1)); + assertMatEqual(truth, dst); + } + public void testPush_back() { Mat m1 = new Mat(2, 4, CvType.CV_32F, new Scalar(2)); Mat m2 = new Mat(3, 4, CvType.CV_32F, new Scalar(3)); @@ -699,6 +741,46 @@ public class MatTest extends OpenCVTestCase { } } + public void testPutIntArrayByteArray() { + Mat m = new Mat(new int[]{5, 5, 5}, CvType.CV_8UC3, new Scalar(1, 2, 3)); + Mat sm = m.submat(new Range[]{ new Range(0, 2), new Range(1, 3), new Range(2, 4)}); + byte[] buff = new byte[] { 0, 0, 0, 0, 0, 0 }; + byte[] buff0 = new byte[] { 10, 20, 30, 40, 50, 60 }; + byte[] buff1 = new byte[] { -1, -2, -3, -4, -5, -6 }; + + int bytesNum = m.put(new int[]{1, 2, 0}, buff0); + + assertEquals(6, bytesNum); + bytesNum = m.get(new int[]{1, 2, 0}, buff); + assertEquals(6, bytesNum); + assertTrue(Arrays.equals(buff, buff0)); + + bytesNum = sm.put(new int[]{0, 0, 0}, buff1); + + assertEquals(6, bytesNum); + bytesNum = sm.get(new int[]{0, 0, 0}, buff); + assertEquals(6, bytesNum); + assertTrue(Arrays.equals(buff, buff1)); + + bytesNum = m.get(new int[]{0, 1, 2}, buff); + assertEquals(6, bytesNum); + assertTrue(Arrays.equals(buff, buff1)); + + Mat m1 = m.submat(new Range[]{ new Range(1,2), Range.all(), Range.all() }); + bytesNum = m1.get(new int[]{ 0, 2, 0}, buff); + assertEquals(6, bytesNum); + assertTrue(Arrays.equals(buff, buff0)); + + try { + byte[] bytes2 = new byte[] { 10, 20, 30, 40, 50 }; + m.put(new int[]{ 2, 2, 0 }, bytes2); + fail("Expected UnsupportedOperationException (data.length % CvType.channels(t) != 0)"); + } catch (UnsupportedOperationException e) { + // expected + } + + } + public void testPutIntIntDoubleArray() { Mat m = new Mat(5, 5, CvType.CV_8UC3, new Scalar(1, 2, 3)); Mat sm = m.submat(2, 4, 3, 5); @@ -722,6 +804,29 @@ public class MatTest extends OpenCVTestCase { assertTrue(Arrays.equals(buff, new byte[]{-1, -2, -3, -4, -5, -6})); } + public void testPutIntArrayDoubleArray() { + Mat m = new Mat(new int[]{5, 5, 5}, CvType.CV_8UC3, new Scalar(1, 2, 3)); + Mat sm = m.submat(new Range[]{ new Range(0, 2), new Range(1, 3), new Range(2, 4)}); + byte[] buff = new byte[] { 0, 0, 0, 0, 0, 0 }; + + int bytesNum = m.put(new int[]{1, 2, 0}, 10, 20, 30, 40, 50, 60); + + assertEquals(6, bytesNum); + bytesNum = m.get(new int[]{1, 2, 0}, buff); + assertEquals(6, bytesNum); + assertTrue(Arrays.equals(buff, new byte[]{10, 20, 30, 40, 50, 60})); + + bytesNum = sm.put(new int[]{0, 0, 0}, 255, 254, 253, 252, 251, 250); + + assertEquals(6, bytesNum); + bytesNum = sm.get(new int[]{0, 0, 0}, buff); + assertEquals(6, bytesNum); + assertTrue(Arrays.equals(buff, new byte[]{-1, -2, -3, -4, -5, -6})); + bytesNum = m.get(new int[]{0, 1, 2}, buff); + assertEquals(6, bytesNum); + assertTrue(Arrays.equals(buff, new byte[]{-1, -2, -3, -4, -5, -6})); + } + public void testPutIntIntFloatArray() { Mat m = new Mat(5, 5, CvType.CV_32FC3, new Scalar(1, 2, 3)); float[] elements = new float[] { 10, 20, 30, 40, 50, 60 }; @@ -745,6 +850,29 @@ public class MatTest extends OpenCVTestCase { } } + public void testPutIntArrayFloatArray() { + Mat m = new Mat(new int[]{5, 5, 5}, CvType.CV_32FC3, new Scalar(1, 2, 3)); + float[] elements = new float[] { 10, 20, 30, 40, 50, 60 }; + + int bytesNum = m.put(new int[]{0, 4, 3}, elements); + + assertEquals(elements.length * 4, bytesNum); + Mat m1 = m.submat(new Range[]{ Range.all(), new Range(4, 5), Range.all() }); + float buff[] = new float[3]; + bytesNum = m1.get(new int[]{ 0, 0, 4 }, buff); + assertEquals(buff.length * 4, bytesNum); + assertTrue(Arrays.equals(new float[]{40, 50, 60}, buff)); + assertArrayEquals(new double[]{10, 20, 30}, m.get(new int[]{ 0, 4, 3 }), EPS); + + try { + float[] elements2 = new float[] { 10, 20, 30, 40, 50 }; + m.put(new int[]{4, 2, 2}, elements2); + fail("Expected UnsupportedOperationException (data.length % CvType.channels(t) != 0)"); + } catch (UnsupportedOperationException e) { + // expected + } + } + public void testPutIntIntIntArray() { Mat m = new Mat(5, 5, CvType.CV_32SC3, new Scalar(-1, -2, -3)); int[] elements = new int[] { 10, 20, 30, 40, 50, 60 }; @@ -768,6 +896,29 @@ public class MatTest extends OpenCVTestCase { } } + public void testPutIntArrayIntArray() { + Mat m = new Mat(new int[]{5, 5, 5}, CvType.CV_32SC3, new Scalar(-1, -2, -3)); + int[] elements = new int[] { 10, 20, 30, 40, 50, 60 }; + + int bytesNum = m.put(new int[]{ 0, 0, 4 }, elements); + + assertEquals(elements.length * 4, bytesNum); + Mat m1 = m.submat(new Range[]{ Range.all(), Range.all(), new Range(4, 5)}); + int buff[] = new int[3]; + bytesNum = m1.get(new int[]{ 0, 0, 0 }, buff); + assertEquals(buff.length * 4, bytesNum); + assertTrue(Arrays.equals(new int[]{ 10, 20, 30 }, buff)); + assertArrayEquals(new double[]{ 40, 50, 60 }, m.get(new int[]{ 0, 1, 0 }), EPS); + + try { + int[] elements2 = new int[] { 10, 20, 30, 40, 50 }; + m.put(new int[] { 2, 2, 0 }, elements2); + fail("Expected UnsupportedOperationException (data.length % CvType.channels(t) != 0)"); + } catch (UnsupportedOperationException e) { + // expected + } + } + public void testPutIntIntShortArray() { Mat m = new Mat(5, 5, CvType.CV_16SC3, new Scalar(-1, -2, -3)); short[] elements = new short[] { 10, 20, 30, 40, 50, 60 }; @@ -790,6 +941,28 @@ public class MatTest extends OpenCVTestCase { } } + public void testPutIntArrayShortArray() { + Mat m = new Mat(new int[]{ 5, 5, 5}, CvType.CV_16SC3, new Scalar(-1, -2, -3)); + short[] elements = new short[] { 10, 20, 30, 40, 50, 60 }; + + int bytesNum = m.put(new int[]{ 0, 2, 3 }, elements); + + assertEquals(elements.length * 2, bytesNum); + Mat m1 = m.submat(new Range[]{ Range.all(), Range.all(), new Range(3, 4)}); + short buff[] = new short[3]; + bytesNum = m1.get(new int[]{ 0, 2, 0 }, buff); + assertTrue(Arrays.equals(new short[]{10, 20, 30}, buff)); + assertArrayEquals(new double[]{40, 50, 60}, m.get(new int[]{ 0, 2, 4 }), EPS); + + try { + short[] elements2 = new short[] { 10, 20, 30, 40, 50 }; + m.put(new int[] { 2, 2, 0 }, elements2); + fail("Expected UnsupportedOperationException (data.length % CvType.channels(t) != 0)"); + } catch (UnsupportedOperationException e) { + // expected + } + } + public void testRelease() { assertFalse(gray0.empty()); assertTrue(gray0.rows() > 0); @@ -818,6 +991,7 @@ public class MatTest extends OpenCVTestCase { } public void testReshapeIntIntArray() { + // 2D -> 4D Mat src = new Mat(6, 5, CvType.CV_8UC3, new Scalar(0)); assertEquals(2, src.dims()); assertEquals(src.rows(), src.size(0)); @@ -828,6 +1002,34 @@ public class MatTest extends OpenCVTestCase { assertEquals(newShape.length, dst.dims()); for (int i = 0; i < newShape.length; ++i) assertEquals(newShape[i], dst.size(i)); + + // 3D -> 2D + src = new Mat(new int[]{4, 6, 7}, CvType.CV_8UC3, new Scalar(0)); + assertEquals(3, src.dims()); + assertEquals(4, src.size(0)); + assertEquals(6, src.size(1)); + assertEquals(7, src.size(2)); + + int[] newShape2 = {src.channels() * src.size(2), src.size(0) * src.size(1)}; + dst = src.reshape(1, newShape2); + assertEquals(newShape2.length, dst.dims()); + for (int i = 0; i < newShape2.length; ++i) + assertEquals(newShape2[i], dst.size(i)); + } + + public void testCopySize() { + Mat src = new Mat(new int[]{1, 1, 10, 10}, CvType.CV_8UC1, new Scalar(1)); + assertEquals(4, src.dims()); + assertEquals(1, src.size(0)); + assertEquals(1, src.size(1)); + assertEquals(10, src.size(2)); + assertEquals(10, src.size(3)); + Mat other = new Mat(new int[]{10, 10}, src.type()); + + src.copySize(other); + assertEquals(other.dims(), src.dims()); + for (int i = 0; i < other.dims(); ++i) + assertEquals(other.size(i), src.size(i)); } public void testRow() { @@ -949,6 +1151,16 @@ public class MatTest extends OpenCVTestCase { assertEquals(2, submat.cols()); } + public void testSubmatRangeArray() { + Mat submat = gray255_32f_3d.submat(new Range[]{ new Range(2, 4), new Range(2, 4), new Range(3, 6) }); + assertTrue(submat.isSubmatrix()); + assertFalse(submat.isContinuous()); + + assertEquals(2, submat.size(0)); + assertEquals(2, submat.size(1)); + assertEquals(3, submat.size(2)); + } + public void testSubmatRect() { Mat submat = gray255.submat(new Rect(5, 5, gray255.cols() / 2, gray255.rows() / 2)); assertTrue(submat.isSubmatrix()); @@ -1015,6 +1227,13 @@ public class MatTest extends OpenCVTestCase { assertMatEqual(truth, dst); } + public void testZerosIntArray() { + dst = Mat.zeros(new int[]{2, 3, 4}, CvType.CV_16S); + + truth = new Mat(new int[]{2, 3, 4}, CvType.CV_16S, new Scalar(0)); + assertMatEqual(truth, dst); + } + public void testMatFromByteBuffer() { ByteBuffer bbuf = ByteBuffer.allocateDirect(64*64); bbuf.putInt(0x01010101); diff --git a/modules/java/generator/src/cpp/Mat.cpp b/modules/java/generator/src/cpp/Mat.cpp index e222cb5..1ae2aa6 100644 --- a/modules/java/generator/src/cpp/Mat.cpp +++ b/modules/java/generator/src/cpp/Mat.cpp @@ -32,6 +32,18 @@ static void throwJavaException(JNIEnv *env, const std::exception *e, const char CV_UNUSED(method); // avoid "unused" warning } +// jint could be int or int32_t so casting jint* to int* in general wouldn't work +static std::vector convertJintArrayToVector(JNIEnv* env, jintArray in) { + std::vector out; + int len = env->GetArrayLength(in); + jint* inArray = env->GetIntArrayElements(in, 0); + for ( int i = 0; i < len; i++ ) { + out.push_back(inArray[i]); + } + env->ReleaseIntArrayElements(in, inArray, 0); + return out; +} + extern "C" { @@ -100,6 +112,30 @@ JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__III return 0; } +// +// Mat::Mat(int[] sizes, int type) +// + +JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__I_3II + (JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type); + +JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__I_3II + (JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type) +{ + static const char method_name[] = "Mat::n_1Mat__I_3II()"; + try { + LOGD("%s", method_name); + std::vector sizes = convertJintArrayToVector(env, sizesArray); + return (jlong) new Mat( ndims, sizes.data(), type ); + } catch(const std::exception &e) { + throwJavaException(env, &e, method_name); + } catch (...) { + throwJavaException(env, 0, method_name); + } + + return 0; +} + // @@ -183,6 +219,33 @@ JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__DDIDDDD // +// Mat::Mat(int[] sizes, int type, Scalar s) +// + +JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__I_3IIDDDD + (JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type, jdouble s_val0, jdouble s_val1, jdouble s_val2, jdouble s_val3); + +JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__I_3IIDDDD + (JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type, jdouble s_val0, jdouble s_val1, jdouble s_val2, jdouble s_val3) +{ + static const char method_name[] = "Mat::n_1Mat__I_3IIDDDD()"; + try { + LOGD("%s", method_name); + std::vector sizes = convertJintArrayToVector(env, sizesArray); + Scalar s(s_val0, s_val1, s_val2, s_val3); + return (jlong) new Mat( ndims, sizes.data(), type, s ); + } catch(const std::exception &e) { + throwJavaException(env, &e, method_name); + } catch (...) { + throwJavaException(env, 0, method_name); + } + + return 0; +} + + + +// // Mat::Mat(Mat m, Range rowRange, Range colRange = Range::all()) // @@ -207,6 +270,59 @@ JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__JIIII return 0; } +jint getObjectIntField(JNIEnv* env, jobject obj, const char * fieldName); + +jint getObjectIntField(JNIEnv* env, jobject obj, const char * fieldName) { + jfieldID fid; /* store the field ID */ + + /* Get a reference to obj's class */ + jclass cls = env->GetObjectClass(obj); + + /* Look for the instance field s in cls */ + fid = env->GetFieldID(cls, fieldName, "I"); + if (fid == NULL) + { + return 0; /* failed to find the field */ + } + + /* Read the instance field s */ + return env->GetIntField(obj, fid); +} + +#define RANGE_START_FIELD "start" +#define RANGE_END_FIELD "end" + +// +// Mat::Mat(Mat m, Range[] ranges) +// + +JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__J_3Lorg_opencv_core_Range_2 + (JNIEnv* env, jclass, jlong m_nativeObj, jobjectArray rangesArray); + +JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__J_3Lorg_opencv_core_Range_2 + (JNIEnv* env, jclass, jlong m_nativeObj, jobjectArray rangesArray) +{ + static const char method_name[] = "Mat::n_1Mat__J_3Lorg_opencv_core_Range_2()"; + try { + LOGD("%s", method_name); + std::vector ranges; + int rangeCount = env->GetArrayLength(rangesArray); + for (int i = 0; i < rangeCount; i++) { + jobject range = env->GetObjectArrayElement(rangesArray, i); + jint start = getObjectIntField(env, range, RANGE_START_FIELD); + jint end = getObjectIntField(env, range, RANGE_END_FIELD); + ranges.push_back(Range(start, end)); + } + return (jlong) new Mat( (*(Mat*)m_nativeObj), ranges ); + } catch(const std::exception &e) { + throwJavaException(env, &e, method_name); + } catch (...) { + throwJavaException(env, 0, method_name); + } + + return 0; +} + JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__JII (JNIEnv* env, jclass, jlong m_nativeObj, jint rowRange_start, jint rowRange_end); @@ -719,6 +835,56 @@ JNIEXPORT void JNICALL Java_org_opencv_core_Mat_n_1create__JDDI // +// void Mat::create(int[] sizes, int type) +// + +JNIEXPORT void JNICALL Java_org_opencv_core_Mat_n_1create__JI_3II + (JNIEnv* env, jclass, jlong self, jint ndims, jintArray sizesArray, jint type); + +JNIEXPORT void JNICALL Java_org_opencv_core_Mat_n_1create__JI_3II + (JNIEnv* env, jclass, jlong self, jint ndims, jintArray sizesArray, jint type) +{ + static const char method_name[] = "Mat::n_1create__JI_3II()"; + try { + LOGD("%s", method_name); + Mat* me = (Mat*) self; + std::vector sizes = convertJintArrayToVector(env, sizesArray); + me->create( ndims, sizes.data(), type ); + } catch(const std::exception &e) { + throwJavaException(env, &e, method_name); + } catch (...) { + throwJavaException(env, 0, method_name); + } +} + + + +// +// Mat Mat::copySize(Mat m) +// + +JNIEXPORT void JNICALL Java_org_opencv_core_Mat_n_1copySize + (JNIEnv* env, jclass, jlong self, jlong m_nativeObj); + +JNIEXPORT void JNICALL Java_org_opencv_core_Mat_n_1copySize + (JNIEnv* env, jclass, jlong self, jlong m_nativeObj) +{ + static const char method_name[] = "Mat::n_1copySize()"; + try { + LOGD("%s", method_name); + Mat* me = (Mat*) self; + Mat& m = *((Mat*)m_nativeObj); + me->copySize( m ); + } catch(const std::exception &e) { + throwJavaException(env, &e, method_name); + } catch (...) { + throwJavaException(env, 0, method_name); + } +} + + + +// // Mat Mat::cross(Mat m) // @@ -1235,6 +1401,33 @@ JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1ones__DDI // +// static Mat Mat::ones(int[] sizes, int type) +// + +JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1ones__I_3II + (JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type); + +JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1ones__I_3II + (JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type) +{ + static const char method_name[] = "Mat::n_1ones__I_3II()"; + try { + LOGD("%s", method_name); + std::vector sizes = convertJintArrayToVector(env, sizesArray); + Mat _retval_ = Mat::ones( ndims, sizes.data(), type ); + return (jlong) new Mat(_retval_); + } catch(const std::exception &e) { + throwJavaException(env, &e, method_name); + } catch (...) { + throwJavaException(env, 0, method_name); + } + + return 0; +} + + + +// // void Mat::push_back(Mat m) // @@ -1344,8 +1537,8 @@ JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1reshape_11 try { LOGD("%s", method_name); Mat* me = (Mat*) self; //TODO: check for NULL - int* newsz = (int*)env->GetPrimitiveArrayCritical(newshape, 0); - Mat _retval_ = me->reshape( cn, newndims, newsz ); + std::vector newsz = convertJintArrayToVector(env, newshape); + Mat _retval_ = me->reshape( cn, newndims, newsz.data() ); return (jlong) new Mat(_retval_); } catch(const std::exception &e) { throwJavaException(env, &e, method_name); @@ -1649,6 +1842,39 @@ JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1submat_1rr return 0; } +// +// Mat Mat::operator()(Range[] ranges) +// + +JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1submat_1ranges +(JNIEnv* env, jclass, jlong self, jobjectArray rangesArray); + +JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1submat_1ranges +(JNIEnv* env, jclass, jlong self, jobjectArray rangesArray) +{ + static const char method_name[] = "Mat::n_1submat_1ranges()"; + try { + LOGD("%s", method_name); + Mat* me = (Mat*) self; + std::vector ranges; + int rangeCount = env->GetArrayLength(rangesArray); + for (int i = 0; i < rangeCount; i++) { + jobject range = env->GetObjectArrayElement(rangesArray, i); + jint start = getObjectIntField(env, range, RANGE_START_FIELD); + jint end = getObjectIntField(env, range, RANGE_END_FIELD); + ranges.push_back(Range(start, end)); + } + Mat _retval_ = me->operator()( ranges ); + return (jlong) new Mat(_retval_); + } catch(const std::exception &e) { + throwJavaException(env, &e, method_name); + } catch (...) { + throwJavaException(env, 0, method_name); + } + + return 0; +} + // @@ -1812,6 +2038,33 @@ JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1zeros__DDI // +// static Mat Mat::zeros(int[] sizes, int type) +// + +JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1zeros__I_3II +(JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type); + +JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1zeros__I_3II +(JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type) +{ + static const char method_name[] = "Mat::n_1zeros__I_3II()"; + try { + LOGD("%s", method_name); + std::vector sizes = convertJintArrayToVector(env, sizesArray); + Mat _retval_ = Mat::zeros( ndims, sizes.data(), type ); + return (jlong) new Mat(_retval_); + } catch(const std::exception &e) { + throwJavaException(env, &e, method_name); + } catch (...) { + throwJavaException(env, 0, method_name); + } + + return 0; +} + + + +// // native support for java finalize() // static void Mat::n_delete( __int64 self ) // @@ -1880,6 +2133,50 @@ template static int mat_put(cv::Mat* m, int row, int col, int count, return res; } +// returns true if final index was reached +static bool updateIdx(cv::Mat* m, std::vector& idx, int inc) { + for (int i=m->dims-1; i>=0; i--) { + if (inc == 0) return false; + idx[i] = (idx[i] + 1) % m->size[i]; + inc--; + } + return true; +} + +template static int mat_put_idx(cv::Mat* m, std::vector& idx, int count, int offset, char* buff) +{ + if(! m) return 0; + if(! buff) return 0; + + count *= sizeof(T); + int rest = (int)m->elemSize(); + for (int i = 0; i < m->dims; i++) { + rest *= (m->size[i] - idx[i]); + } + if(count>rest) count = rest; + int res = count; + + if( m->isContinuous() ) + { + memcpy(m->ptr(idx.data()), buff + offset, count); + } else { + // dim by dim + int num = (m->size[m->dims-1] - idx[m->dims-1]) * (int)m->elemSize(); // 1st partial row + if(countptr(idx.data()); + while(count>0){ + memcpy(data, buff + offset, num); + updateIdx(m, idx, num / (int)m->elemSize()); + count -= num; + buff += num; + num = m->size[m->dims-1] * (int)m->elemSize(); + if(countptr(idx.data()); + } + } + return res; +} + template static jint java_mat_put(JNIEnv* env, jlong self, jint row, jint col, jint count, jint offset, ARRAY vals) { static const char *method_name = JavaOpenCVTrait::put; @@ -1903,6 +2200,31 @@ template static jint java_mat_put(JNIEnv* env, jlong self, jint row return 0; } +template static jint java_mat_put_idx(JNIEnv* env, jlong self, jintArray idxArray, jint count, jint offset, ARRAY vals) +{ + static const char *method_name = JavaOpenCVTrait::put; + try { + LOGD("%s", method_name); + cv::Mat* me = (cv::Mat*) self; + if(! self) return 0; // no native object behind + if(me->depth() != JavaOpenCVTrait::cvtype_1 && me->depth() != JavaOpenCVTrait::cvtype_2) return 0; // incompatible type + std::vector idx = convertJintArrayToVector(env, idxArray); + for (int i = 0; i < me->dims ; i++ ) { + if (me->size[i]<=idx[i]) return 0; + } + char* values = (char*)env->GetPrimitiveArrayCritical(vals, 0); + int res = mat_put_idx::value_type>(me, idx, count, offset, values); + env->ReleasePrimitiveArrayCritical(vals, values, JNI_ABORT); + return res; + } catch(const std::exception &e) { + throwJavaException(env, &e, method_name); + } catch (...) { + throwJavaException(env, 0, method_name); + } + + return 0; +} + extern "C" { JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutB @@ -1914,6 +2236,15 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutB return java_mat_put(env, self, row, col, count, 0, vals); } +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutBIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jbyteArray vals); + +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutBIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jbyteArray vals) +{ + return java_mat_put_idx(env, self, idxArray, count, 0, vals); +} + JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutBwOffset (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jint offset, jbyteArray vals); @@ -1923,6 +2254,15 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutBwOffset return java_mat_put(env, self, row, col, count, offset, vals); } +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutBwIdxOffset + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jint offset, jbyteArray vals); + +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutBwIdxOffset + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jint offset, jbyteArray vals) +{ + return java_mat_put_idx(env, self, idxArray, count, offset, vals); +} + JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutS (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jshortArray vals); @@ -1932,6 +2272,15 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutS return java_mat_put(env, self, row, col, count, 0, vals); } +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutSIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jshortArray vals); + +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutSIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jshortArray vals) +{ + return java_mat_put_idx(env, self, idxArray, count, 0, vals); +} + JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutI (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jintArray vals); @@ -1941,6 +2290,15 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutI return java_mat_put(env, self, row, col, count, 0, vals); } +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutIIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jintArray vals); + +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutIIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jintArray vals) +{ + return java_mat_put_idx(env, self, idxArray, count, 0, vals); +} + JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutF (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jfloatArray vals); @@ -1950,6 +2308,15 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutF return java_mat_put(env, self, row, col, count, 0, vals); } +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutFIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jfloatArray vals); + +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutFIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jfloatArray vals) +{ + return java_mat_put_idx(env, self, idxArray, count, 0, vals); +} + // unlike other nPut()-s this one (with double[]) should convert input values to correct type #define PUT_ITEM(T, R, C) { T*dst = (T*)me->ptr(R, C); for(int ch=0; chchannels() && count>0; count--,ch++,src++,dst++) *dst = cv::saturate_cast(*src); } @@ -2010,6 +2377,56 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutD return 0; } +// unlike other nPut()-s this one (with double[]) should convert input values to correct type +#define PUT_ITEM_IDX(T, I) { T*dst = (T*)me->ptr(I); for(int ch=0; chchannels() && count>0; count--,ch++,src++,dst++) *dst = cv::saturate_cast(*src); } + +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutDIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jdoubleArray vals); + +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutDIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jdoubleArray vals) +{ + static const char* method_name = JavaOpenCVTrait::put; + try { + LOGD("%s", method_name); + cv::Mat* me = (cv::Mat*) self; + if(!me || !me->data) return 0; // no native object behind + std::vector idx = convertJintArrayToVector(env, idxArray); + for (int i=0; idims; i++) { + if (me->size[i]<=idx[i]) return 0; // indexes out of range + } + int rest = me->channels(); + for (int i=0; idims; i++) { + rest *= (me->size[i] - idx[i]); + } + if(count>rest) count = rest; + int res = count; + double* values = (double*)env->GetPrimitiveArrayCritical(vals, 0); + double* src = values; + bool reachedFinalIndex = false; + for(; !reachedFinalIndex && count>0; reachedFinalIndex = updateIdx(me, idx, 1)) + { + switch(me->depth()) { + case CV_8U: PUT_ITEM_IDX(uchar, idx.data()); break; + case CV_8S: PUT_ITEM_IDX(schar, idx.data()); break; + case CV_16U: PUT_ITEM_IDX(ushort, idx.data()); break; + case CV_16S: PUT_ITEM_IDX(short, idx.data()); break; + case CV_32S: PUT_ITEM_IDX(int, idx.data()); break; + case CV_32F: PUT_ITEM_IDX(float, idx.data()); break; + case CV_64F: PUT_ITEM_IDX(double, idx.data()); break; + } + } + env->ReleasePrimitiveArrayCritical(vals, values, 0); + return res; + } catch(const std::exception &e) { + throwJavaException(env, &e, method_name); + } catch (...) { + throwJavaException(env, 0, method_name); + } + + return 0; +} + } // extern "C" template static int mat_get(cv::Mat* m, int row, int col, int count, char* buff) @@ -2042,6 +2459,40 @@ template static int mat_get(cv::Mat* m, int row, int col, int count, return res; } +template static int mat_get_idx(cv::Mat* m, std::vector& idx, int count, char* buff) +{ + if(! m) return 0; + if(! buff) return 0; + + count *= sizeof(T); + int rest = (int)m->elemSize(); + for (int i = 0; i < m->dims; i++) { + rest *= (m->size[i] - idx[i]); + } + if(count>rest) count = rest; + int res = count; + + if( m->isContinuous() ) + { + memcpy(buff, m->ptr(idx.data()), count); + } else { + // dim by dim + int num = (m->size[m->dims-1] - idx[m->dims-1]) * (int)m->elemSize(); // 1st partial row + if(countptr(idx.data()); + while(count>0){ + memcpy(buff, data, num); + updateIdx(m, idx, num / (int)m->elemSize()); + count -= num; + buff += num; + num = m->size[m->dims-1] * (int)m->elemSize(); + if(countptr(idx.data()); + } + } + return res; +} + template static jint java_mat_get(JNIEnv* env, jlong self, jint row, jint col, jint count, ARRAY vals) { static const char *method_name = JavaOpenCVTrait::get; try { @@ -2064,6 +2515,31 @@ template static jint java_mat_get(JNIEnv* env, jlong self, jint row return 0; } +template static jint java_mat_get_idx(JNIEnv* env, jlong self, jintArray idxArray, jint count, ARRAY vals) { + static const char *method_name = JavaOpenCVTrait::get; + try { + LOGD("%s", method_name); + cv::Mat* me = (cv::Mat*) self; + if(! self) return 0; // no native object behind + if(me->depth() != JavaOpenCVTrait::cvtype_1 && me->depth() != JavaOpenCVTrait::cvtype_2) return 0; // incompatible type + std::vector idx = convertJintArrayToVector(env, idxArray); + for (int i = 0; i < me->dims ; i++ ) { + if (me->size[i]<=idx[i]) return 0; + } + + char* values = (char*)env->GetPrimitiveArrayCritical(vals, 0); + int res = mat_get_idx::value_type>(me, idx, count, values); + env->ReleasePrimitiveArrayCritical(vals, values, 0); + return res; + } catch(const std::exception &e) { + throwJavaException(env, &e, method_name); + } catch (...) { + throwJavaException(env, 0, method_name); + } + + return 0; +} + extern "C" { JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetB @@ -2075,6 +2551,15 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetB return java_mat_get(env, self, row, col, count, vals); } +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetBIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jbyteArray vals); + +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetBIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jbyteArray vals) +{ + return java_mat_get_idx(env, self, idxArray, count, vals); +} + JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetS (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jshortArray vals); @@ -2084,6 +2569,15 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetS return java_mat_get(env, self, row, col, count, vals); } +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetSIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jshortArray vals); + +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetSIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jshortArray vals) +{ + return java_mat_get_idx(env, self, idxArray, count, vals); +} + JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetI (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jintArray vals); @@ -2093,6 +2587,15 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetI return java_mat_get(env, self, row, col, count, vals); } +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetIIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jintArray vals); + +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetIIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jintArray vals) +{ + return java_mat_get_idx(env, self, idxArray, count, vals); +} + JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetF (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jfloatArray vals); @@ -2102,6 +2605,15 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetF return java_mat_get(env, self, row, col, count, vals); } +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetFIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jfloatArray vals); + +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetFIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jfloatArray vals) +{ + return java_mat_get_idx(env, self, idxArray, count, vals); +} + JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetD (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jdoubleArray vals); @@ -2111,6 +2623,15 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetD return java_mat_get(env, self, row, col, count, vals); } +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetDIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jdoubleArray vals); + +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetDIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jdoubleArray vals) +{ + return java_mat_get_idx(env, self, idxArray, count, vals); +} + JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Mat_nGet (JNIEnv* env, jclass, jlong self, jint row, jint col); @@ -2149,6 +2670,47 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Mat_nGet return 0; } +JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Mat_nGetIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray); + +JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Mat_nGetIdx + (JNIEnv* env, jclass, jlong self, jintArray idxArray) +{ + static const char method_name[] = "Mat::nGetIdx()"; + try { + LOGD("%s", method_name); + cv::Mat* me = (cv::Mat*) self; + if(! self) return 0; // no native object behind + std::vector idx = convertJintArrayToVector(env, idxArray); + for (int i=0; idims; i++) { + if (me->size[i]<=idx[i]) return 0; // indexes out of range + } + + jdoubleArray res = env->NewDoubleArray(me->channels()); + if(res){ + jdouble buff[CV_CN_MAX];//me->channels() + int i; + switch(me->depth()){ + case CV_8U: for(i=0; ichannels(); i++) buff[i] = *((unsigned char*) me->ptr(idx.data()) + i); break; + case CV_8S: for(i=0; ichannels(); i++) buff[i] = *((signed char*) me->ptr(idx.data()) + i); break; + case CV_16U: for(i=0; ichannels(); i++) buff[i] = *((unsigned short*)me->ptr(idx.data()) + i); break; + case CV_16S: for(i=0; ichannels(); i++) buff[i] = *((signed short*) me->ptr(idx.data()) + i); break; + case CV_32S: for(i=0; ichannels(); i++) buff[i] = *((int*) me->ptr(idx.data()) + i); break; + case CV_32F: for(i=0; ichannels(); i++) buff[i] = *((float*) me->ptr(idx.data()) + i); break; + case CV_64F: for(i=0; ichannels(); i++) buff[i] = *((double*) me->ptr(idx.data()) + i); break; + } + env->SetDoubleArrayRegion(res, 0, me->channels(), buff); + } + return res; + } catch(const std::exception &e) { + throwJavaException(env, &e, method_name); + } catch (...) { + throwJavaException(env, 0, method_name); + } + + return 0; +} + JNIEXPORT jstring JNICALL Java_org_opencv_core_Mat_nDump (JNIEnv *env, jclass, jlong self); diff --git a/modules/java/test/android_test/src/org/opencv/test/OpenCVTestCase.java b/modules/java/test/android_test/src/org/opencv/test/OpenCVTestCase.java index c3af0b3..cc7eb9d 100644 --- a/modules/java/test/android_test/src/org/opencv/test/OpenCVTestCase.java +++ b/modules/java/test/android_test/src/org/opencv/test/OpenCVTestCase.java @@ -99,6 +99,8 @@ public class OpenCVTestCase extends TestCase { protected Mat rgbLena; protected Mat grayChess; + protected Mat gray255_32f_3d; + protected Mat v1; protected Mat v2; @@ -149,6 +151,8 @@ public class OpenCVTestCase extends TestCase { rgbLena = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH); grayChess = Imgcodecs.imread(OpenCVTestRunner.CHESS_PATH, 0); + gray255_32f_3d = new Mat(new int[]{matSize, matSize, matSize}, CvType.CV_32F, new Scalar(255.0)); + v1 = new Mat(1, 3, CvType.CV_32F); v1.put(0, 0, 1.0, 3.0, 2.0); v2 = new Mat(1, 3, CvType.CV_32F); @@ -184,6 +188,7 @@ public class OpenCVTestCase extends TestCase { rgba128.release(); rgbLena.release(); grayChess.release(); + gray255_32f_3d.release(); v1.release(); v2.release(); @@ -442,8 +447,24 @@ public class OpenCVTestCase extends TestCase { assertEquals(msg, expected.z, actual.z, eps); } + static private boolean dimensionsEqual(Mat expected, Mat actual) { + if (expected.dims() != actual.dims()) { + return false; + } + if (expected.dims() > 2) { + for (int i = 0; i < expected.dims(); i++) { + if (expected.size(i) != actual.size(i)) { + return false; + } + } + return true; + } else { + return expected.cols() == actual.cols() && expected.rows() == actual.rows(); + } + } + static private void compareMats(Mat expected, Mat actual, boolean isEqualityMeasured) { - if (expected.type() != actual.type() || expected.cols() != actual.cols() || expected.rows() != actual.rows()) { + if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) { throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual); } @@ -471,7 +492,7 @@ public class OpenCVTestCase extends TestCase { } static private void compareMats(Mat expected, Mat actual, double eps, boolean isEqualityMeasured) { - if (expected.type() != actual.type() || expected.cols() != actual.cols() || expected.rows() != actual.rows()) { + if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) { throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual); } diff --git a/modules/java/test/pure_test/src/org/opencv/test/OpenCVTestCase.java b/modules/java/test/pure_test/src/org/opencv/test/OpenCVTestCase.java index a66206e..7dc3432 100644 --- a/modules/java/test/pure_test/src/org/opencv/test/OpenCVTestCase.java +++ b/modules/java/test/pure_test/src/org/opencv/test/OpenCVTestCase.java @@ -97,6 +97,8 @@ public class OpenCVTestCase extends TestCase { protected Mat rgbLena; protected Mat grayChess; + protected Mat gray255_32f_3d; + protected Mat v1; protected Mat v2; @@ -175,6 +177,8 @@ public class OpenCVTestCase extends TestCase { rgbLena = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH); grayChess = Imgcodecs.imread(OpenCVTestRunner.CHESS_PATH, 0); + gray255_32f_3d = new Mat(new int[]{matSize, matSize, matSize}, CvType.CV_32F, new Scalar(255.0)); + v1 = new Mat(1, 3, CvType.CV_32F); v1.put(0, 0, 1.0, 3.0, 2.0); v2 = new Mat(1, 3, CvType.CV_32F); @@ -210,6 +214,7 @@ public class OpenCVTestCase extends TestCase { rgba128.release(); rgbLena.release(); grayChess.release(); + gray255_32f_3d.release(); v1.release(); v2.release(); @@ -468,8 +473,24 @@ public class OpenCVTestCase extends TestCase { assertEquals(msg, expected.z, actual.z, eps); } + static private boolean dimensionsEqual(Mat expected, Mat actual) { + if (expected.dims() != actual.dims()) { + return false; + } + if (expected.dims() > 2) { + for (int i = 0; i < expected.dims(); i++) { + if (expected.size(i) != actual.size(i)) { + return false; + } + } + return true; + } else { + return expected.cols() == actual.cols() && expected.rows() == actual.rows(); + } + } + static private void compareMats(Mat expected, Mat actual, boolean isEqualityMeasured) { - if (expected.type() != actual.type() || expected.cols() != actual.cols() || expected.rows() != actual.rows()) { + if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) { throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual); } @@ -497,7 +518,7 @@ public class OpenCVTestCase extends TestCase { } static private void compareMats(Mat expected, Mat actual, double eps, boolean isEqualityMeasured) { - if (expected.type() != actual.type() || expected.cols() != actual.cols() || expected.rows() != actual.rows()) { + if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) { throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual); }