From 3936130d14c15f8b2db2e4a5b2c75722211f5e1e Mon Sep 17 00:00:00 2001 From: rainyl Date: Wed, 20 Mar 2024 11:59:11 +0800 Subject: [PATCH] fix #8, add binary_version, make Mat impl ffi.Finalizable directly --- .gitignore | 2 +- CMakeLists.txt | 2 +- bin/setup_commands.dart | 17 ++-- lib/src/core/mat.dart | 208 ++++++++++++++++++--------------------- lib/src/core/scalar.dart | 25 +++-- lib/src/dnn/dnn.dart | 2 +- pubspec.yaml | 1 + test/imgproc_test.dart | 32 ++++++ test/mat_test.dart | 2 - 9 files changed, 148 insertions(+), 143 deletions(-) diff --git a/.gitignore b/.gitignore index e195378a..4376e3a5 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,7 @@ ffigen_contrib.yaml ffigen_cuda.yaml replace.py generate.py -demo.c +demo.* coverage/ pkgs/ __pycache__ diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ce10f4b..7ccf555f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,7 @@ target_compile_definitions(${library_name} PUBLIC DART_SHARED_LIB) if(WITH_OPENCV_DART_DEMO) add_executable( demo - "demo.c" + "src/demo.cxx" ) target_link_libraries( demo diff --git a/bin/setup_commands.dart b/bin/setup_commands.dart index 3d5ea7da..73c7f017 100644 --- a/bin/setup_commands.dart +++ b/bin/setup_commands.dart @@ -58,20 +58,17 @@ abstract class BaseSetupCommand extends Command { final opencvRoot = packageConfigFile.uri.resolve(pkg['rootUri'] ?? ''); print('Using package:$setupPkgName from ${opencvRoot.toFilePath()}'); - final doc = loadYaml( - File("${opencvRoot.toFilePath()}/pubspec.yaml").readAsStringSync()); - final _version = doc["version"] as String; + final doc = loadYaml(File("${opencvRoot.toFilePath()}/pubspec.yaml").readAsStringSync()); + final _version = doc["binary_version"] as String; final libTarName = "libopencv_dart-$os-$arch.tar.gz"; final version = _version.replaceAll(RegExp(r"\-dev.*"), ""); print('Downloading prebuilt binary...'); - String url = - "https://github.com/rainyl/opencv_dart/releases/download/v$version/$libTarName"; + String url = "https://github.com/rainyl/opencv_dart/releases/download/v$version/$libTarName"; final cacheTarPath = p.join(opencvRoot.toFilePath(), ".cache", libTarName); final saveFile = File(cacheTarPath); - if (!saveFile.parent.existsSync()) - saveFile.parent.createSync(recursive: true); + if (!saveFile.parent.existsSync()) saveFile.parent.createSync(recursive: true); print("Downloading $url"); final request = await HttpClient().getUrl(Uri.parse(url)); @@ -94,8 +91,7 @@ abstract class BaseSetupCommand extends Command { extractPath = p.join(opencvRoot.toFilePath(), "linux"); break; case OS.android: - extractPath = p.join( - opencvRoot.toFilePath(), "android", "src", "main", "jniLibs", arch); + extractPath = p.join(opencvRoot.toFilePath(), "android", "src", "main", "jniLibs", arch); case OS.macos: extractPath = p.join(opencvRoot.toFilePath(), "macos"); case OS.ios: @@ -109,8 +105,7 @@ abstract class BaseSetupCommand extends Command { } final tarBytes = GZipDecoder().decodeBytes(saveFile.readAsBytesSync()); final archive = TarDecoder().decodeBytes(tarBytes); - extractArchiveToDisk(archive, extractPath, - bufferSize: 1024 * 1024 * 10); // 10MB + extractArchiveToDisk(archive, extractPath, bufferSize: 1024 * 1024 * 10); // 10MB } @override diff --git a/lib/src/core/mat.dart b/lib/src/core/mat.dart index 5867645f..93c0fb2d 100644 --- a/lib/src/core/mat.dart +++ b/lib/src/core/mat.dart @@ -13,9 +13,9 @@ import '../opencv.g.dart' as cvg; final _bindings = cvg.CvNative(loadNativeLibrary()); -class Mat extends CvObject with EquatableMixin { - Mat._(this._ptr) : super(_ptr) { - _finalizer.attach(this, _ptr); +class Mat with EquatableMixin implements ffi.Finalizable { + Mat._(this.ptr) { + _finalizer.attach(this, ptr); } factory Mat.fromCMat(cvg.Mat mat) => Mat._(mat); @@ -88,24 +88,24 @@ class Mat extends CvObject with EquatableMixin { } static final _finalizer = ffi.NativeFinalizer(_bindings.addresses.Mat_Close); - cvg.Mat _ptr; - MatType get _type => MatType(_bindings.Mat_Type(_ptr)); - int get width => _bindings.Mat_Cols(_ptr); - int get height => _bindings.Mat_Rows(_ptr); - int get cols => _bindings.Mat_Cols(_ptr); - int get rows => _bindings.Mat_Rows(_ptr); - int get channels => _bindings.Mat_Channels(_ptr); - int get total => _bindings.Mat_Total(_ptr); - bool get isEmpty => _bindings.Mat_Empty(_ptr); - bool get isContinus => _bindings.Mat_IsContinuous(_ptr); - int get step => _bindings.Mat_Step(_ptr); - int get elemSize => _bindings.Mat_ElemSize(_ptr); + cvg.Mat ptr; + MatType get _type => MatType(_bindings.Mat_Type(ptr)); + int get width => _bindings.Mat_Cols(ptr); + int get height => _bindings.Mat_Rows(ptr); + int get cols => _bindings.Mat_Cols(ptr); + int get rows => _bindings.Mat_Rows(ptr); + int get channels => _bindings.Mat_Channels(ptr); + int get total => _bindings.Mat_Total(ptr); + bool get isEmpty => _bindings.Mat_Empty(ptr); + bool get isContinus => _bindings.Mat_IsContinuous(ptr); + int get step => _bindings.Mat_Step(ptr); + int get elemSize => _bindings.Mat_ElemSize(ptr); /// (rows, cols) List get size { return using>((arena) { final s = arena(); - _bindings.Mat_Size(_ptr, s); + _bindings.Mat_Size(ptr, s); final ss = List.generate(s.ref.length, (index) => s.ref.val[index]); return ss; }); @@ -120,7 +120,7 @@ class Mat extends CvObject with EquatableMixin { /// only for channels == 1 int get countNoneZero { assert(channels == 1, "countNoneZero only for channels == 1"); - return _bindings.Mat_CountNonZero(_ptr); + return _bindings.Mat_CountNonZero(ptr); } T at(int row, int col, {int? cn}) { @@ -128,32 +128,32 @@ class Mat extends CvObject with EquatableMixin { switch (type.depth) { case MatType.CV_8U: vDouble = type.channels == 1 || cn == null - ? _bindings.Mat_GetUChar(_ptr, row, col).toDouble() - : _bindings.Mat_GetUChar3(_ptr, row, col, cn).toDouble(); + ? _bindings.Mat_GetUChar(ptr, row, col).toDouble() + : _bindings.Mat_GetUChar3(ptr, row, col, cn).toDouble(); case MatType.CV_8S: vDouble = type.channels == 1 || cn == null - ? _bindings.Mat_GetSChar(_ptr, row, col).toDouble() - : _bindings.Mat_GetSChar3(_ptr, row, col, cn).toDouble(); + ? _bindings.Mat_GetSChar(ptr, row, col).toDouble() + : _bindings.Mat_GetSChar3(ptr, row, col, cn).toDouble(); case MatType.CV_16U: vDouble = type.channels == 1 || cn == null - ? _bindings.Mat_GetUShort(_ptr, row, col).toDouble() - : _bindings.Mat_GetUShort3(_ptr, row, col, cn).toDouble(); + ? _bindings.Mat_GetUShort(ptr, row, col).toDouble() + : _bindings.Mat_GetUShort3(ptr, row, col, cn).toDouble(); case MatType.CV_16S: vDouble = type.channels == 1 || cn == null - ? _bindings.Mat_GetShort(_ptr, row, col).toDouble() - : _bindings.Mat_GetShort3(_ptr, row, col, cn).toDouble(); + ? _bindings.Mat_GetShort(ptr, row, col).toDouble() + : _bindings.Mat_GetShort3(ptr, row, col, cn).toDouble(); case MatType.CV_32S: vDouble = type.channels == 1 || cn == null - ? _bindings.Mat_GetInt(_ptr, row, col).toDouble() - : _bindings.Mat_GetInt3(_ptr, row, col, cn).toDouble(); + ? _bindings.Mat_GetInt(ptr, row, col).toDouble() + : _bindings.Mat_GetInt3(ptr, row, col, cn).toDouble(); case MatType.CV_32F: vDouble = type.channels == 1 || cn == null - ? _bindings.Mat_GetFloat(_ptr, row, col).toDouble() - : _bindings.Mat_GetFloat3(_ptr, row, col, cn).toDouble(); + ? _bindings.Mat_GetFloat(ptr, row, col).toDouble() + : _bindings.Mat_GetFloat3(ptr, row, col, cn).toDouble(); case MatType.CV_64F: vDouble = type.channels == 1 || cn == null - ? _bindings.Mat_GetDouble(_ptr, row, col).toDouble() - : _bindings.Mat_GetDouble3(_ptr, row, col, cn).toDouble(); + ? _bindings.Mat_GetDouble(ptr, row, col).toDouble() + : _bindings.Mat_GetDouble3(ptr, row, col, cn).toDouble(); default: throw UnsupportedError("at() for $type is not supported!"); } @@ -169,38 +169,38 @@ class Mat extends CvObject with EquatableMixin { case MatType.CV_8U: assert(T == int, "$type only support int"); type.channels == 1 || cn == null - ? _bindings.Mat_SetUChar(_ptr, row, col, val as int) - : _bindings.Mat_SetUChar3(_ptr, row, col, cn, val as int); + ? _bindings.Mat_SetUChar(ptr, row, col, val as int) + : _bindings.Mat_SetUChar3(ptr, row, col, cn, val as int); case MatType.CV_8S: assert(T == int, "$type only support int"); type.channels == 1 || cn == null - ? _bindings.Mat_SetSChar(_ptr, row, col, val as int) - : _bindings.Mat_SetSChar3(_ptr, row, col, cn, val as int); + ? _bindings.Mat_SetSChar(ptr, row, col, val as int) + : _bindings.Mat_SetSChar3(ptr, row, col, cn, val as int); case MatType.CV_16U: assert(T == int, "$type only support int"); type.channels == 1 || cn == null - ? _bindings.Mat_SetUShort(_ptr, row, col, val as int) - : _bindings.Mat_SetUShort3(_ptr, row, col, cn, val as int); + ? _bindings.Mat_SetUShort(ptr, row, col, val as int) + : _bindings.Mat_SetUShort3(ptr, row, col, cn, val as int); case MatType.CV_16S: assert(T == int, "$type only support int"); type.channels == 1 || cn == null - ? _bindings.Mat_SetShort(_ptr, row, col, val as int) - : _bindings.Mat_SetShort3(_ptr, row, col, cn, val as int); + ? _bindings.Mat_SetShort(ptr, row, col, val as int) + : _bindings.Mat_SetShort3(ptr, row, col, cn, val as int); case MatType.CV_32S: assert(T == int, "$type only support int"); type.channels == 1 || cn == null - ? _bindings.Mat_SetInt(_ptr, row, col, val as int) - : _bindings.Mat_SetInt3(_ptr, row, col, cn, val as int); + ? _bindings.Mat_SetInt(ptr, row, col, val as int) + : _bindings.Mat_SetInt3(ptr, row, col, cn, val as int); case MatType.CV_32F: assert(T == double, "$type only support double"); type.channels == 1 || cn == null - ? _bindings.Mat_SetFloat(_ptr, row, col, val as double) - : _bindings.Mat_SetFloat3(_ptr, row, col, cn, val as double); + ? _bindings.Mat_SetFloat(ptr, row, col, val as double) + : _bindings.Mat_SetFloat3(ptr, row, col, cn, val as double); case MatType.CV_64F: assert(T == double, "$type only support double"); type.channels == 1 || cn == null - ? _bindings.Mat_SetDouble(_ptr, row, col, val as double) - : _bindings.Mat_SetDouble3(_ptr, row, col, cn, val as double); + ? _bindings.Mat_SetDouble(ptr, row, col, val as double) + : _bindings.Mat_SetDouble3(ptr, row, col, cn, val as double); default: throw UnsupportedError("setValue() for $type is not supported!"); } @@ -243,11 +243,11 @@ class Mat extends CvObject with EquatableMixin { Mat addMat(Mat other, {bool inplace = false}) { assert(other.type == type, "${this.type} != ${other.type}"); if (inplace) { - _bindings.Mat_Add(_ptr, other.ptr, _ptr); + _bindings.Mat_Add(ptr, other.ptr, ptr); return this; } else { final dst = Mat.empty(); - _bindings.Mat_Add(_ptr, other.ptr, dst.ptr); + _bindings.Mat_Add(ptr, other.ptr, dst.ptr); return dst; } } @@ -255,7 +255,7 @@ class Mat extends CvObject with EquatableMixin { Mat addU8(int val, {bool inplace = false}) { assert(type.depth == MatType.CV_8U && val >= CV_U8_MIN && val <= CV_U8_MAX, "addU8() only for CV_8U"); if (inplace) { - _bindings.Mat_AddUChar(_ptr, val); + _bindings.Mat_AddUChar(ptr, val); return this; } else { final dst = this.clone(); @@ -265,10 +265,9 @@ class Mat extends CvObject with EquatableMixin { } Mat addI32(int val, {bool inplace = false}) { - assert( - type.depth == MatType.CV_32S && val >= CV_I32_MIN && val <= CV_I32_MAX, "addI32() only for CV_32S"); + assert(type.depth == MatType.CV_32S && val >= CV_I32_MIN && val <= CV_I32_MAX, "addI32() only for CV_32S"); if (inplace) { - _bindings.Mat_AddI32(_ptr, val); + _bindings.Mat_AddI32(ptr, val); return this; } else { final dst = this.clone(); @@ -280,7 +279,7 @@ class Mat extends CvObject with EquatableMixin { Mat addF32(double val, {bool inplace = false}) { assert(type.depth == MatType.CV_32F && val <= CV_F32_MAX, "addF32() only for CV_32F"); if (inplace) { - _bindings.Mat_AddFloat(_ptr, val); + _bindings.Mat_AddFloat(ptr, val); return this; } else { final dst = this.clone(); @@ -292,7 +291,7 @@ class Mat extends CvObject with EquatableMixin { Mat addF64(double val, {bool inplace = false}) { assert(type.depth == MatType.CV_64F && val <= CV_F64_MAX, "addF64() only for CV_64F"); if (inplace) { - _bindings.Mat_AddF64(_ptr, val); + _bindings.Mat_AddF64(ptr, val); return this; } else { final dst = this.clone(); @@ -331,20 +330,19 @@ class Mat extends CvObject with EquatableMixin { Mat subtractMat(Mat other, {bool inplace = false}) { assert(other.type == type, "${this.type} != ${other.type}"); if (inplace) { - _bindings.Mat_Subtract(_ptr, other.ptr, _ptr); + _bindings.Mat_Subtract(ptr, other.ptr, ptr); return this; } else { final dst = Mat.empty(); - _bindings.Mat_Subtract(_ptr, other.ptr, dst.ptr); + _bindings.Mat_Subtract(ptr, other.ptr, dst.ptr); return dst; } } Mat subtractU8(int val, {bool inplace = false}) { - assert( - type.depth == MatType.CV_8U && val >= CV_U8_MIN && val <= CV_U8_MAX, "subtractU8() only for CV_8U"); + assert(type.depth == MatType.CV_8U && val >= CV_U8_MIN && val <= CV_U8_MAX, "subtractU8() only for CV_8U"); if (inplace) { - _bindings.Mat_SubtractUChar(_ptr, val); + _bindings.Mat_SubtractUChar(ptr, val); return this; } else { final dst = this.clone(); @@ -354,10 +352,9 @@ class Mat extends CvObject with EquatableMixin { } Mat subtractI32(int val, {bool inplace = false}) { - assert(type.depth == MatType.CV_32S && val >= CV_I32_MIN && val <= CV_I32_MAX, - "subtractI32() only for CV_32S"); + assert(type.depth == MatType.CV_32S && val >= CV_I32_MIN && val <= CV_I32_MAX, "subtractI32() only for CV_32S"); if (inplace) { - _bindings.Mat_SubtractI32(_ptr, val); + _bindings.Mat_SubtractI32(ptr, val); return this; } else { final dst = this.clone(); @@ -369,7 +366,7 @@ class Mat extends CvObject with EquatableMixin { Mat subtractF32(double val, {bool inplace = false}) { assert(type.depth == MatType.CV_32F && val <= CV_F32_MAX, "subtractF32() only for CV_32F"); if (inplace) { - _bindings.Mat_SubtractFloat(_ptr, val); + _bindings.Mat_SubtractFloat(ptr, val); return this; } else { final dst = this.clone(); @@ -381,7 +378,7 @@ class Mat extends CvObject with EquatableMixin { Mat subtractF64(double val, {bool inplace = false}) { assert(type.depth == MatType.CV_64F && val <= CV_F64_MAX, "subtractF64() only for CV_64F"); if (inplace) { - _bindings.Mat_SubtractF64(_ptr, val); + _bindings.Mat_SubtractF64(ptr, val); return this; } else { final dst = this.clone(); @@ -420,20 +417,19 @@ class Mat extends CvObject with EquatableMixin { Mat multiplyMat(Mat other, {bool inplace = false}) { assert(other.type == type, "${this.type} != ${other.type}"); if (inplace) { - _bindings.Mat_Multiply(_ptr, other.ptr, _ptr); + _bindings.Mat_Multiply(ptr, other.ptr, ptr); return this; } else { final dst = Mat.empty(); - _bindings.Mat_Multiply(_ptr, other.ptr, dst.ptr); + _bindings.Mat_Multiply(ptr, other.ptr, dst.ptr); return dst; } } Mat multiplyU8(int val, {bool inplace = false}) { - assert( - type.depth == MatType.CV_8U && val >= CV_U8_MIN && val <= CV_U8_MAX, "multiplyU8() only for CV_8U"); + assert(type.depth == MatType.CV_8U && val >= CV_U8_MIN && val <= CV_U8_MAX, "multiplyU8() only for CV_8U"); if (inplace) { - _bindings.Mat_MultiplyUChar(_ptr, val); + _bindings.Mat_MultiplyUChar(ptr, val); return this; } else { final dst = this.clone(); @@ -443,10 +439,9 @@ class Mat extends CvObject with EquatableMixin { } Mat multiplyI32(int val, {bool inplace = false}) { - assert(type.depth == MatType.CV_32S && val >= CV_I32_MIN && val <= CV_I32_MAX, - "multiplyI32() only for CV_32S"); + assert(type.depth == MatType.CV_32S && val >= CV_I32_MIN && val <= CV_I32_MAX, "multiplyI32() only for CV_32S"); if (inplace) { - _bindings.Mat_MultiplyI32(_ptr, val); + _bindings.Mat_MultiplyI32(ptr, val); return this; } else { final dst = this.clone(); @@ -458,7 +453,7 @@ class Mat extends CvObject with EquatableMixin { Mat multiplyF32(double val, {bool inplace = false}) { assert(type.depth == MatType.CV_32F && val <= CV_F32_MAX, "multiplyF32() only for CV_32F"); if (inplace) { - _bindings.Mat_MultiplyFloat(_ptr, val); + _bindings.Mat_MultiplyFloat(ptr, val); return this; } else { final dst = this.clone(); @@ -470,7 +465,7 @@ class Mat extends CvObject with EquatableMixin { Mat multiplyF64(double val, {bool inplace = false}) { assert(type.depth == MatType.CV_64F && val <= CV_F64_MAX, "multiplyF64() only for CV_64F"); if (inplace) { - _bindings.Mat_MultiplyF64(_ptr, val); + _bindings.Mat_MultiplyF64(ptr, val); return this; } else { final dst = this.clone(); @@ -509,11 +504,11 @@ class Mat extends CvObject with EquatableMixin { Mat divideMat(Mat other, {bool inplace = false}) { assert(other.type == type, "${this.type} != ${other.type}"); if (inplace) { - _bindings.Mat_Divide(_ptr, other.ptr, _ptr); + _bindings.Mat_Divide(ptr, other.ptr, ptr); return this; } else { final dst = Mat.empty(); - _bindings.Mat_Divide(_ptr, other.ptr, dst.ptr); + _bindings.Mat_Divide(ptr, other.ptr, dst.ptr); return dst; } } @@ -521,7 +516,7 @@ class Mat extends CvObject with EquatableMixin { Mat divideU8(int val, {bool inplace = false}) { assert(type.depth == MatType.CV_8U && val >= CV_U8_MIN && val <= CV_U8_MAX, "divideU8() only for CV_8U"); if (inplace) { - _bindings.Mat_DivideUChar(_ptr, val); + _bindings.Mat_DivideUChar(ptr, val); return this; } else { final dst = this.clone(); @@ -531,10 +526,9 @@ class Mat extends CvObject with EquatableMixin { } Mat divideI32(int val, {bool inplace = false}) { - assert(type.depth == MatType.CV_32S && val >= CV_I32_MIN && val <= CV_I32_MAX, - "divideI32() only for CV_32S"); + assert(type.depth == MatType.CV_32S && val >= CV_I32_MIN && val <= CV_I32_MAX, "divideI32() only for CV_32S"); if (inplace) { - _bindings.Mat_DivideI32(_ptr, val); + _bindings.Mat_DivideI32(ptr, val); return this; } else { final dst = this.clone(); @@ -546,7 +540,7 @@ class Mat extends CvObject with EquatableMixin { Mat divideF32(double val, {bool inplace = false}) { assert(type.depth == MatType.CV_32F && val <= CV_F32_MAX, "divideF32() only for CV_32F"); if (inplace) { - _bindings.Mat_DivideFloat(_ptr, val); + _bindings.Mat_DivideFloat(ptr, val); return this; } else { final dst = this.clone(); @@ -558,7 +552,7 @@ class Mat extends CvObject with EquatableMixin { Mat divideF64(double val, {bool inplace = false}) { assert(type.depth == MatType.CV_64F && val <= CV_F64_MAX, "divideF64() only for CV_64F"); if (inplace) { - _bindings.Mat_DivideF64(_ptr, val); + _bindings.Mat_DivideF64(ptr, val); return this; } else { final dst = this.clone(); @@ -569,61 +563,61 @@ class Mat extends CvObject with EquatableMixin { Mat transpose({bool inplace = false}) { final dst = inplace ? this : Mat.empty(); - final code = _bindings.Mat_Transpose(_ptr, dst.ptr); + final code = _bindings.Mat_Transpose(ptr, dst.ptr); if (code == ErrorCode.StsOk.code) return dst; throw Exception("transpose() failed with code $code"); } - Mat clone() => Mat._(_bindings.Mat_Clone(_ptr)); + Mat clone() => Mat._(_bindings.Mat_Clone(ptr)); void copyTo(Mat dst) { - _bindings.Mat_CopyTo(_ptr, dst.ptr); + _bindings.Mat_CopyTo(ptr, dst.ptr); } void copyToWithMask(Mat dst, Mat mask) { - _bindings.Mat_CopyToWithMask(_ptr, dst.ptr, mask.ptr); + _bindings.Mat_CopyToWithMask(ptr, dst.ptr, mask.ptr); } Mat convertTo(MatType type, {double alpha = 1, double beta = 0}) { final dst = Mat.empty(); - _bindings.Mat_ConvertToWithParams(_ptr, dst.ptr, type.toInt32(), alpha, beta); + _bindings.Mat_ConvertToWithParams(ptr, dst.ptr, type.toInt32(), alpha, beta); return dst; } Mat region(Rect rect) { assert(rect.x + rect.width <= width && rect.y + rect.height <= height, "rect is out of range"); - return Mat._(_bindings.Mat_Region(_ptr, rect.ref)); + return Mat._(_bindings.Mat_Region(ptr, rect.ref)); } - Mat reshape(int cn, int rows) => Mat._(_bindings.Mat_Reshape(_ptr, cn, rows)); + Mat reshape(int cn, int rows) => Mat._(_bindings.Mat_Reshape(ptr, cn, rows)); Mat rotate(int rotationCode, {bool inplace = false}) { if (inplace) { - _bindings.Rotate(_ptr, _ptr, rotationCode); + _bindings.Rotate(ptr, ptr, rotationCode); return this; } else { final dst = this.clone(); - _bindings.Rotate(_ptr, dst.ptr, rotationCode); + _bindings.Rotate(ptr, dst.ptr, rotationCode); return dst; } } Mat rowRange(int start, int end) { - return Mat.fromCMat(_bindings.Mat_rowRange(_ptr, start, end)); + return Mat.fromCMat(_bindings.Mat_rowRange(ptr, start, end)); } Mat colRange(int start, int end) { - return Mat.fromCMat(_bindings.Mat_colRange(_ptr, start, end)); + return Mat.fromCMat(_bindings.Mat_colRange(ptr, start, end)); } - Mat convertToFp16() => Mat._(_bindings.Mat_ConvertFp16(_ptr)); + Mat convertToFp16() => Mat._(_bindings.Mat_ConvertFp16(ptr)); Scalar mean({Mat? mask}) { final cvg.Scalar s; if (mask == null) { - s = _bindings.Mat_Mean(_ptr); + s = _bindings.Mat_Mean(ptr); } else { - s = _bindings.Mat_MeanWithMask(_ptr, mask.ptr); + s = _bindings.Mat_MeanWithMask(ptr, mask.ptr); } return Scalar.fromNative(s); } @@ -631,17 +625,17 @@ class Mat extends CvObject with EquatableMixin { /// Calculates a square root of array elements. Mat sqrt() { assert(type.depth == MatType.CV_32F || type.depth == MatType.CV_64F, "sqrt() only for CV_32F or CV_64F"); - return Mat._(_bindings.Mat_Sqrt(_ptr)); + return Mat._(_bindings.Mat_Sqrt(ptr)); } /// Sum calculates the per-channel pixel sum of an image. - Scalar sum() => Scalar.fromNative(_bindings.Mat_Sum(_ptr)); + Scalar sum() => Scalar.fromNative(_bindings.Mat_Sum(ptr)); /// PatchNaNs converts NaN's to zeros. - void patchNaNs({double val = 0}) => _bindings.Mat_PatchNaNs(_ptr, val); + void patchNaNs({double val = 0}) => _bindings.Mat_PatchNaNs(ptr, val); Mat setTo(Scalar s) { - _bindings.Mat_SetTo(_ptr, s.ref); + _bindings.Mat_SetTo(ptr, s.ref); return this; } @@ -665,15 +659,8 @@ class Mat extends CvObject with EquatableMixin { return List.generate(4, (cn) => toList(cn: cn)); } - @override - cvg.Mat get ptr => _ptr; - - set ptr(cvg.Mat value) { - _ptr = value; - } - Uint8List get data { - final _data = _bindings.Mat_DataPtr(_ptr); + final _data = _bindings.Mat_DataPtr(ptr); return _data.data.cast().asTypedList(_data.length); } @@ -686,12 +673,7 @@ class Mat extends CvObject with EquatableMixin { // } @override - ffi.NativeType get ref => throw UnsupportedError("Mat has no Native type"); - @override - ffi.NativeType toNative() => throw UnsupportedError("Mat has no Native type"); - - @override - List get props => [_ptr.address]; + List get props => [ptr.address]; } typedef OutputArray = Mat; diff --git a/lib/src/core/scalar.dart b/lib/src/core/scalar.dart index 2119c814..3b0b410e 100644 --- a/lib/src/core/scalar.dart +++ b/lib/src/core/scalar.dart @@ -2,12 +2,11 @@ import 'dart:ffi' as ffi; import 'package:equatable/equatable.dart'; import 'package:ffi/ffi.dart'; -import 'base.dart'; import '../opencv.g.dart' as cvg; -class Scalar extends CvObject with EquatableMixin { - Scalar._(this._ptr) : super(_ptr) { - _finalizer.attach(this, _ptr); +class Scalar with EquatableMixin implements ffi.Finalizable { + Scalar._(this.ptr) { + _finalizer.attach(this, ptr); } factory Scalar(double val1, double val2, double val3, double val4) { @@ -20,23 +19,21 @@ class Scalar extends CvObject with EquatableMixin { } factory Scalar.fromNative(cvg.Scalar s) => Scalar(s.val1, s.val2, s.val3, s.val4); factory Scalar.all(double val) => Scalar(val, val, val, val); - factory Scalar.default_() => Scalar(double.maxFinite, double.maxFinite, double.maxFinite, double.maxFinite); + factory Scalar.default_() => Scalar(0.0, 0.0, 0.0, 0.0); factory Scalar.fromRgb(int r, int g, int b) { return Scalar(b.toDouble(), g.toDouble(), r.toDouble(), 0); } static final _finalizer = Finalizer>((p0) => calloc.free(p0)); - double get val1 => _ptr.ref.val1; - double get val2 => _ptr.ref.val2; - double get val3 => _ptr.ref.val3; - double get val4 => _ptr.ref.val4; + double get val1 => ptr.ref.val1; + double get val2 => ptr.ref.val2; + double get val3 => ptr.ref.val3; + double get val4 => ptr.ref.val4; - ffi.Pointer _ptr; + ffi.Pointer ptr; - @override - cvg.Scalar get ref => _ptr.ref; - @override - cvg.Scalar toNative() => _ptr.ref; + cvg.Scalar get ref => ptr.ref; + cvg.Scalar toNative() => ptr.ref; @override List get props => [val1, val2, val3, val4]; diff --git a/lib/src/dnn/dnn.dart b/lib/src/dnn/dnn.dart index df5625aa..ee3255d9 100644 --- a/lib/src/dnn/dnn.dart +++ b/lib/src/dnn/dnn.dart @@ -212,7 +212,7 @@ class Net implements ffi.Finalizable { /// SetInput sets the new value for the layer output blob. /// /// For further details, please see: - /// https://docs.opencv.org/trunk/db/d30/classcv_1_1dnn_1_1Net.html#a672a08ae76444d75d05d7bfea3e4a328 + /// https://docs.opencv.org/4.x/db/d30/classcv_1_1dnn_1_1Net.html#a5e74adacffd6aa53d56046581de7fcbd void setInput(InputArray blob, {String name = "", double scalefactor = 1.0, Scalar? mean}) { mean ??= Scalar.default_(); using((arena) { diff --git a/pubspec.yaml b/pubspec.yaml index 9bcd90a4..648de36d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,7 @@ name: opencv_dart description: "OpenCV4 bindings for Dart language and Flutter, using dart:ffi. The most complete OpenCV bindings for Dart!" version: 0.6.5 +binary_version: 0.6.5 homepage: https://github.com/rainyl/opencv_dart environment: diff --git a/test/imgproc_test.dart b/test/imgproc_test.dart index 0eece132..140f1d51 100644 --- a/test/imgproc_test.dart +++ b/test/imgproc_test.dart @@ -922,4 +922,36 @@ void main() async { cv.accumulateWeighted(src, dst, 0.1, mask: mask); expect(dst.isEmpty, false); }); + + test("Issue 8", () { + cv.Mat mask = cv.Mat.ones(512, 512, cv.MatType.CV_32FC1); + + List faceTemplate = [ + cv.Point2f(192.98138, 239.94708), + cv.Point2f(318.90277, 240.1936), + cv.Point2f(256.63416, 314.01935), + cv.Point2f(201.26117, 371.41043), + cv.Point2f(314.08905, 371.15118) + ]; + + List landmarks = [ + cv.Point2f(916.1744018554688, 436.8168579101563), + cv.Point2f(1179.1181030273438, 448.0384765625), + cv.Point2f(1039.171106147766, 604.8748825073242), + cv.Point2f(908.7911743164062, 683.4760314941407), + cv.Point2f(1167.2201416015625, 693.495068359375), + ]; + + var (affineMatrix, _) = cv.estimateAffinePartial2D(landmarks, faceTemplate, method: cv.LMEDS); + + var invMask = cv.Mat.empty(); + cv.warpAffine(mask, invMask, affineMatrix, (2048, 2048)); + + for (int i = 0; i < 2047; i++) { + for (int j = 0; j < 2047; j++) { + var val = invMask.at(i, j); + expect(val == 0 || val == 1, true); + } + } + }); } diff --git a/test/mat_test.dart b/test/mat_test.dart index 589e8734..ff0e3291 100644 --- a/test/mat_test.dart +++ b/test/mat_test.dart @@ -223,8 +223,6 @@ void main() async { test('Mat test others', () { final mat0 = cv.Mat.ones(200, 100, cv.MatType.CV_8UC3); - expect(() => mat0.ref, throwsUnsupportedError); - expect(() => mat0.toNative(), throwsUnsupportedError); expect(mat0.props, equals([mat0.ptr.address])); final data = mat0.data; expect(data.length, greaterThan(0));