From 8b61719a9d50597b92b2ebc8c0e2133b0d8d6f69 Mon Sep 17 00:00:00 2001 From: Giles Payne Date: Thu, 3 Sep 2020 21:31:11 +0900 Subject: [PATCH] Swift native in/out array handling --- .../calib3d/misc/objc/test/Calib3dTest.swift | 10 +- .../core/misc/objc/common/ByteVectorExt.swift | 13 ++ modules/core/misc/objc/gen_dict.json | 85 ++++++--- modules/core/misc/objc/test/CoreTest.swift | 38 ++-- modules/dnn/misc/objc/gen_dict.json | 1 + .../misc/objc/test/ImgcodecsTest.swift | 22 +-- modules/imgproc/misc/objc/gen_dict.json | 4 + .../imgproc/misc/objc/test/ImgprocTest.swift | 102 +++++----- .../imgproc/misc/objc/test/Subdiv2DTest.swift | 4 +- modules/objc/generator/gen_objc.py | 176 ++++++++++++++++-- modules/objc/test/test/OpenCVTestCase.swift | 4 +- .../ColorBlobDetector.swift | 14 +- .../FaceDetection/ViewController.swift | 10 +- 13 files changed, 347 insertions(+), 136 deletions(-) diff --git a/modules/calib3d/misc/objc/test/Calib3dTest.swift b/modules/calib3d/misc/objc/test/Calib3dTest.swift index 85786e2fde..3fe4cb8dae 100644 --- a/modules/calib3d/misc/objc/test/Calib3dTest.swift +++ b/modules/calib3d/misc/objc/test/Calib3dTest.swift @@ -378,15 +378,15 @@ class Calib3dTest: OpenCVTestCase { try points3d.put(row: i, col: 0, data: [0, y, x]) // add(Point3(0, y, x)) } - let rvecs = NSMutableArray() - let tvecs = NSMutableArray() + var rvecs = [Mat]() + var tvecs = [Mat]() let rvec = Mat() let tvec = Mat() let reprojectionError = Mat(rows: 2, cols: 1, type: CvType.CV_64FC1) - Calib3d.solvePnPGeneric(objectPoints: points3d, imagePoints: points2d, cameraMatrix: intrinsics, distCoeffs: MatOfDouble(), rvecs: rvecs, tvecs: tvecs, useExtrinsicGuess: false, flags: .SOLVEPNP_IPPE, rvec: rvec, tvec: tvec, reprojectionError: reprojectionError) + Calib3d.solvePnPGeneric(objectPoints: points3d, imagePoints: points2d, cameraMatrix: intrinsics, distCoeffs: MatOfDouble(), rvecs: &rvecs, tvecs: &tvecs, useExtrinsicGuess: false, flags: .SOLVEPNP_IPPE, rvec: rvec, tvec: tvec, reprojectionError: reprojectionError) let truth_rvec = Mat(rows: 3, cols: 1, type: CvType.CV_64F) try truth_rvec.put(row: 0, col: 0, data: [0, .pi / 2, 0] as [Double]) @@ -394,8 +394,8 @@ class Calib3dTest: OpenCVTestCase { let truth_tvec = Mat(rows: 3, cols: 1, type: CvType.CV_64F) try truth_tvec.put(row: 0, col: 0, data: [-320, -240, 400] as [Double]) - try assertMatEqual(truth_rvec, rvecs[0] as! Mat, 10 * OpenCVTestCase.EPS) - try assertMatEqual(truth_tvec, tvecs[0] as! Mat, 1000 * OpenCVTestCase.EPS) + try assertMatEqual(truth_rvec, rvecs[0], 10 * OpenCVTestCase.EPS) + try assertMatEqual(truth_tvec, tvecs[0], 1000 * OpenCVTestCase.EPS) } func testGetDefaultNewCameraMatrixMat() { diff --git a/modules/core/misc/objc/common/ByteVectorExt.swift b/modules/core/misc/objc/common/ByteVectorExt.swift index e553de0aa4..05b7d9d59c 100644 --- a/modules/core/misc/objc/common/ByteVectorExt.swift +++ b/modules/core/misc/objc/common/ByteVectorExt.swift @@ -12,6 +12,11 @@ public extension ByteVector { self.init(data:data); } + convenience init(_ array:[UInt8]) { + let data = array.withUnsafeBufferPointer { Data(buffer: $0) } + self.init(data:data); + } + subscript(index: Int) -> Int8 { get { return self.get(index) @@ -25,6 +30,14 @@ public extension ByteVector { return ret } } + + var unsignedArray: [UInt8] { + get { + var ret = Array(repeating: 0, count: data.count/MemoryLayout.stride) + _ = ret.withUnsafeMutableBytes { data.copyBytes(to: $0) } + return ret + } + } } extension ByteVector : Sequence { diff --git a/modules/core/misc/objc/gen_dict.json b/modules/core/misc/objc/gen_dict.json index 1d7d5d6d25..4cb8133dc4 100644 --- a/modules/core/misc/objc/gen_dict.json +++ b/modules/core/misc/objc/gen_dict.json @@ -112,7 +112,14 @@ "Point": { "objc_type": "Point2i*", "to_cpp": "%(n)s.nativeRef", - "from_cpp": "[Point2i fromNative:%(n)s]" + "from_cpp": "[Point2i fromNative:%(n)s]", + "swift_type": "Point" + }, + "Point2i": { + "objc_type": "Point2i*", + "to_cpp": "%(n)s.nativeRef", + "from_cpp": "[Point2i fromNative:%(n)s]", + "swift_type": "Point" }, "Point2f": { "objc_type": "Point2f*", @@ -145,12 +152,14 @@ "Rect": { "objc_type": "Rect2i*", "to_cpp": "%(n)s.nativeRef", - "from_cpp": "[Rect2i fromNative:%(n)s]" + "from_cpp": "[Rect2i fromNative:%(n)s]", + "swift_type": "Rect" }, "Rect2i": { "objc_type": "Rect2i*", "to_cpp": "%(n)s.nativeRef", - "from_cpp": "[Rect2i fromNative:%(n)s]" + "from_cpp": "[Rect2i fromNative:%(n)s]", + "swift_type": "Rect" }, "Rect2f": { "objc_type": "Rect2f*", @@ -175,7 +184,14 @@ "Size": { "objc_type": "Size2i*", "to_cpp": "%(n)s.nativeRef", - "from_cpp": "[Size2i fromNative:%(n)s]" + "from_cpp": "[Size2i fromNative:%(n)s]", + "swift_type": "Size" + }, + "Size2i": { + "objc_type": "Size2i*", + "to_cpp": "%(n)s.nativeRef", + "from_cpp": "[Size2i fromNative:%(n)s]", + "swift_type": "Size" }, "Size2f": { "objc_type": "Size2f*", @@ -190,12 +206,14 @@ "String": { "objc_type": "NSString*", "to_cpp": "cv::String(%(n)s.UTF8String)", - "from_cpp": "[NSString stringWithUTF8String:%(n)s.c_str()]" + "from_cpp": "[NSString stringWithUTF8String:%(n)s.c_str()]", + "swift_type": "String" }, "std::string": { "objc_type": "NSString*", "to_cpp": "std::string(%(n)s.UTF8String)", - "from_cpp": "[NSString stringWithUTF8String:%(n)s.c_str()]" + "from_cpp": "[NSString stringWithUTF8String:%(n)s.c_str()]", + "swift_type": "String" }, "TermCriteria": { "objc_type": "TermCriteria*", @@ -230,7 +248,8 @@ "c_string": { "objc_type": "NSString*", "to_cpp": "%(n)s.UTF8String", - "from_cpp": "[NSString stringWithUTF8String:%(n)s]" + "from_cpp": "[NSString stringWithUTF8String:%(n)s]", + "swift_type": "String" }, "vector_DMatch": { "objc_type": "DMatch*", @@ -246,7 +265,8 @@ }, "vector_Point": { "objc_type": "Point2i*", - "v_type": "Point" + "v_type": "Point2i", + "swift_type": "[Point]" }, "vector_Point2f": { "objc_type": "Point2f*", @@ -270,7 +290,8 @@ }, "vector_Rect": { "objc_type": "Rect2i*", - "v_type": "Rect2i" + "v_type": "Rect2i", + "swift_type": "[Rect]" }, "vector_Rect2d": { "objc_type": "Rect2d*", @@ -282,11 +303,13 @@ }, "vector_String": { "objc_type": "NSString*", - "v_type": "String" + "v_type": "String", + "swift_type": "[String]" }, "vector_string": { "objc_type": "NSString*", - "v_type": "std::string" + "v_type": "std::string", + "swift_type": "[String]" }, "vector_Vec4f": { "objc_type": "Float4*", @@ -304,31 +327,42 @@ "objc_type": "ByteVector*", "to_cpp": "%(n)s.nativeRef", "from_cpp": "[ByteVector fromNative:%(n)s]", - "cast_to": "std::vector" + "cast_to": "std::vector", + "primitive_vector": true, + "swift_type": "[Int8]" }, "vector_double": { "objc_type": "DoubleVector*", "to_cpp": "%(n)s.nativeRef", "from_cpp": "[DoubleVector fromNative:%(n)s]", - "cast_to": "std::vector" + "cast_to": "std::vector", + "primitive_vector": true, + "swift_type": "[Double]" }, "vector_float": { "objc_type": "FloatVector*", "to_cpp": "%(n)s.nativeRef", "from_cpp": "[FloatVector fromNative:%(n)s]", - "cast_to": "std::vector" + "cast_to": "std::vector", + "primitive_vector": true, + "swift_type": "[Float]" }, "vector_int": { "objc_type": "IntVector*", "to_cpp": "%(n)s.nativeRef", "from_cpp": "[IntVector fromNative:%(n)s]", - "cast_to": "std::vector" + "cast_to": "std::vector", + "primitive_vector": true, + "swift_type": "[Int32]" }, "vector_uchar": { "objc_type": "ByteVector*", "to_cpp": "(std::vector&)%(n)s.nativeRef", "from_cpp": "[ByteVector fromNative:(std::vector&)%(n)s]", - "cast_to": "std::vector" + "cast_to": "std::vector", + "primitive_vector": true, + "swift_type": "[UInt8]", + "unsigned": true }, "vector_vector_Mat": { "objc_type": "Mat*", @@ -344,7 +378,8 @@ }, "vector_vector_Point": { "objc_type": "Point2i*", - "v_v_type": "Point" + "v_v_type": "Point2i", + "swift_type": "[[Point]]" }, "vector_vector_Point2f": { "objc_type": "Point2f*", @@ -356,19 +391,27 @@ }, "vector_vector_char": { "objc_type": "ByteVector*", - "v_type": "ByteVector" + "v_type": "ByteVector", + "primitive_vector_vector": true, + "swift_type": "[[Int8]]" }, "vector_vector_int": { "objc_type": "IntVector*", - "v_type": "IntVector" + "v_type": "IntVector", + "primitive_vector_vector": true, + "swift_type": "[[Int32]]" }, "vector_vector_float": { "objc_type": "FloatVector*", - "v_type": "FloatVector" + "v_type": "FloatVector", + "primitive_vector_vector": true, + "swift_type": "[[Float]]" }, "vector_vector_double": { "objc_type": "DoubleVector*", - "v_type": "DoubleVector" + "v_type": "DoubleVector", + "primitive_vector_vector": true, + "swift_type": "[[Double]]" }, "ByteVector": { "objc_type": "ByteVector*", diff --git a/modules/core/misc/objc/test/CoreTest.swift b/modules/core/misc/objc/test/CoreTest.swift index efa18bbd7f..535675a775 100644 --- a/modules/core/misc/objc/test/CoreTest.swift +++ b/modules/core/misc/objc/test/CoreTest.swift @@ -854,15 +854,15 @@ class CoreTest: OpenCVTestCase { } func testMeanStdDevMatMatMat() { - let mean = DoubleVector() - let stddev = DoubleVector() - Core.meanStdDev(src: rgbLena, mean: mean, stddev: stddev) + var mean = [Double]() + var stddev = [Double]() + Core.meanStdDev(src: rgbLena, mean: &mean, stddev: &stddev) let expectedMean = [105.3989906311035, 99.56269836425781, 179.7303047180176] let expectedDev = [33.74205485167219, 52.8734582803278, 49.01569488056406] - assertArrayEquals(expectedMean as [NSNumber], mean.array as [NSNumber], OpenCVTestCase.EPS) - assertArrayEquals(expectedDev as [NSNumber], stddev.array as [NSNumber], OpenCVTestCase.EPS) + assertArrayEquals(expectedMean, mean, OpenCVTestCase.EPS) + assertArrayEquals(expectedDev, stddev, OpenCVTestCase.EPS) } func testMeanStdDevMatMatMatMat() { @@ -871,16 +871,16 @@ class CoreTest: OpenCVTestCase { let mask = gray0.clone() submat = mask.submat(rowStart: 0, rowEnd: mask.rows() / 2, colStart: 0, colEnd: mask.cols() / 2) submat.setTo(scalar: Scalar(1)) - let mean = DoubleVector() - let stddev = DoubleVector() + var mean = [Double]() + var stddev = [Double]() - Core.meanStdDev(src: grayRnd, mean: mean, stddev: stddev, mask: mask) + Core.meanStdDev(src: grayRnd, mean: &mean, stddev: &stddev, mask: mask) - let expectedMean = [33] - let expectedDev = [0] + let expectedMean = [33.0] + let expectedDev = [0.0] - assertArrayEquals(expectedMean as [NSNumber], mean.array as [NSNumber], OpenCVTestCase.EPS) - assertArrayEquals(expectedDev as [NSNumber], stddev.array as [NSNumber], OpenCVTestCase.EPS) + assertArrayEquals(expectedMean, mean, OpenCVTestCase.EPS) + assertArrayEquals(expectedDev, stddev, OpenCVTestCase.EPS) } func testMerge() throws { @@ -940,14 +940,14 @@ class CoreTest: OpenCVTestCase { rgba0Copy.setTo(scalar: Scalar(10, 20, 30, 40)) let src = [rgba0Copy] let dst = [gray3, gray2, gray1, gray0, getMat(CvType.CV_8UC3, vals: [0, 0, 0])] - let fromTo = IntVector([ + let fromTo:[Int32] = [ 3, 0, 3, 1, 2, 2, 0, 3, 2, 4, 1, 5, - 0, 6]) + 0, 6] Core.mixChannels(src: src, dst: dst, fromTo: fromTo) @@ -1530,13 +1530,13 @@ class CoreTest: OpenCVTestCase { func testSplit() throws { let m = getMat(CvType.CV_8UC3, vals: [1, 2, 3]) - let cois = NSMutableArray() + var cois = [Mat]() - Core.split(m: m, mv: cois) + Core.split(m: m, mv: &cois) - try assertMatEqual(gray1, cois[0] as! Mat) - try assertMatEqual(gray2, cois[1] as! Mat) - try assertMatEqual(gray3, cois[2] as! Mat) + try assertMatEqual(gray1, cois[0]) + try assertMatEqual(gray2, cois[1]) + try assertMatEqual(gray3, cois[2]) } func testSqrt() throws { diff --git a/modules/dnn/misc/objc/gen_dict.json b/modules/dnn/misc/objc/gen_dict.json index 869183fe4d..e6d561fba0 100644 --- a/modules/dnn/misc/objc/gen_dict.json +++ b/modules/dnn/misc/objc/gen_dict.json @@ -13,6 +13,7 @@ "Net": { "(void)forward:(NSMutableArray*)outputBlobs outputName:(NSString*)outputName" : { "forward" : {"name" : "forwardOutputBlobs"} }, "(void)forward:(NSMutableArray*)outputBlobs outBlobNames:(NSArray*)outBlobNames" : { "forward" : {"name" : "forwardOutputBlobs"} }, + "(void)forwardAndRetrieve:(NSMutableArray*>*)outputBlobs outBlobNames:(NSArray*)outBlobNames" : { "forward" : {"swift_name" : "forwardAndRetrieve"} }, "(long)getFLOPS:(IntVector*)netInputShape" : { "getFLOPS" : {"name" : "getFLOPSWithNetInputShape"} }, "(long)getFLOPS:(NSArray*)netInputShapes" : { "getFLOPS" : {"name" : "getFLOPSWithNetInputShapes"} }, "(long)getFLOPS:(int)layerId netInputShape:(IntVector*)netInputShape" : { "getFLOPS" : {"name" : "getFLOPSWithLayerId"} }, diff --git a/modules/imgcodecs/misc/objc/test/ImgcodecsTest.swift b/modules/imgcodecs/misc/objc/test/ImgcodecsTest.swift index 857c95ed74..92d507efa5 100644 --- a/modules/imgcodecs/misc/objc/test/ImgcodecsTest.swift +++ b/modules/imgcodecs/misc/objc/test/ImgcodecsTest.swift @@ -12,23 +12,23 @@ class ImgcodecsTest: OpenCVTestCase { let LENA_PATH = Bundle(for: ImgcodecsTest.self).path(forResource:"lena", ofType:"png", inDirectory:"resources")! func testImencodeStringMatListOfByte() { - let buff = ByteVector() - XCTAssert(Imgcodecs.imencode(ext: ".jpg", img: gray127, buf: buff)) - XCTAssertFalse(0 == buff.length) + var buff = [UInt8]() + XCTAssert(Imgcodecs.imencode(ext: ".jpg", img: gray127, buf: &buff)) + XCTAssertFalse(0 == buff.count) } func testImencodeStringMatListOfByteListOfInteger() { - let params40 = IntVector([ImwriteFlags.IMWRITE_JPEG_QUALITY.rawValue, 40]) - let params90 = IntVector([ImwriteFlags.IMWRITE_JPEG_QUALITY.rawValue, 90]) + let params40:[Int32] = [ImwriteFlags.IMWRITE_JPEG_QUALITY.rawValue, 40] + let params90:[Int32] = [ImwriteFlags.IMWRITE_JPEG_QUALITY.rawValue, 90] - let buff40 = ByteVector() - let buff90 = ByteVector() + var buff40 = [UInt8]() + var buff90 = [UInt8]() - XCTAssert(Imgcodecs.imencode(ext: ".jpg", img: rgbLena, buf: buff40, params: params40)) - XCTAssert(Imgcodecs.imencode(ext: ".jpg", img: rgbLena, buf: buff90, params: params90)) + XCTAssert(Imgcodecs.imencode(ext: ".jpg", img: rgbLena, buf: &buff40, params: params40)) + XCTAssert(Imgcodecs.imencode(ext: ".jpg", img: rgbLena, buf: &buff90, params: params90)) - XCTAssert(buff40.length > 0) - XCTAssert(buff40.length < buff90.length) + XCTAssert(buff40.count > 0) + XCTAssert(buff40.count < buff90.count) } func testImreadString() { diff --git a/modules/imgproc/misc/objc/gen_dict.json b/modules/imgproc/misc/objc/gen_dict.json index 1bb2d54808..043baa5a5b 100644 --- a/modules/imgproc/misc/objc/gen_dict.json +++ b/modules/imgproc/misc/objc/gen_dict.json @@ -1,4 +1,8 @@ { + "enum_ignore_list" : [ + "MorphShapes_c", + "SmoothMethod_c" + ], "module_imports": ["Size2i"], "const_ignore_list": [ "CV_TM_.+", diff --git a/modules/imgproc/misc/objc/test/ImgprocTest.swift b/modules/imgproc/misc/objc/test/ImgprocTest.swift index c7668836fb..72432ceb4a 100644 --- a/modules/imgproc/misc/objc/test/ImgprocTest.swift +++ b/modules/imgproc/misc/objc/test/ImgprocTest.swift @@ -125,13 +125,13 @@ class ImgprocTest: OpenCVTestCase { func testApproxPolyDP() { let curve = [Point2f(x: 1, y: 3), Point2f(x: 2, y: 4), Point2f(x: 3, y: 5), Point2f(x: 4, y: 4), Point2f(x: 5, y: 3)] - let approxCurve = NSMutableArray() + var approxCurve = [Point2f]() - Imgproc.approxPolyDP(curve: curve, approxCurve: approxCurve, epsilon: OpenCVTestCase.EPS, closed: true) + Imgproc.approxPolyDP(curve: curve, approxCurve: &approxCurve, epsilon: OpenCVTestCase.EPS, closed: true) let approxCurveGold = [Point2f(x: 1, y: 3), Point2f(x: 3, y: 5), Point2f(x: 5, y: 3)] - XCTAssert(approxCurve as! [Point2f] == approxCurveGold) + XCTAssert(approxCurve == approxCurveGold) } func testArcLength() { @@ -201,9 +201,9 @@ class ImgprocTest: OpenCVTestCase { func testCalcBackProject() { let images = [grayChess] - let channels = IntVector([0]) - let histSize = IntVector([10]) - let ranges = FloatVector([0, 256]) + let channels:[Int32] = [0] + let histSize:[Int32] = [10] + let ranges:[Float] = [0, 256] let hist = Mat() Imgproc.calcHist(images: images, channels: channels, mask: Mat(), hist: hist, histSize: histSize, ranges: ranges) @@ -218,9 +218,9 @@ class ImgprocTest: OpenCVTestCase { func testCalcHistListOfMatListOfIntegerMatMatListOfIntegerListOfFloat() throws { let images = [gray128] - let channels = IntVector([0]) - let histSize = IntVector([10]) - let ranges = FloatVector([0, 256]) + let channels:[Int32] = [0] + let histSize:[Int32] = [10] + let ranges:[Float] = [0, 256] let hist = Mat() Imgproc.calcHist(images: images, channels: channels, mask: Mat(), hist: hist, histSize: histSize, ranges: ranges) @@ -232,9 +232,9 @@ class ImgprocTest: OpenCVTestCase { func testCalcHistListOfMatListOfIntegerMatMatListOfIntegerListOfFloat2D() throws { let images = [gray255, gray128] - let channels = IntVector([0, 1]) - let histSize = IntVector([10, 10]) - let ranges = FloatVector([0, 256, 0, 256]) + let channels:[Int32] = [0, 1] + let histSize:[Int32] = [10, 10] + let ranges:[Float] = [0, 256, 0, 256] let hist = Mat() Imgproc.calcHist(images: images, channels: channels, mask: Mat(), hist: hist, histSize: histSize, ranges: ranges) @@ -250,11 +250,11 @@ class ImgprocTest: OpenCVTestCase { let hist3D = Mat() let histList = [Mat(), Mat(), Mat()] - let histSize = IntVector([10]) - let ranges = FloatVector([0, 256]) + let histSize: [Int32] = [10] + let ranges: [Float] = [0, 256] for i:Int in 0..