Skip to content

Commit

Permalink
Merge pull request #338 from rainyl/mat-at-set
Browse files Browse the repository at this point in the history
remove Mat.fromPtr, merge it to Mat.fromMat
add Mat.atU8, Mat.setU8, etc.
  • Loading branch information
rainyl authored Feb 11, 2025
2 parents 7cda0ee + 4a25f0c commit 266c7c5
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 92 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@ name: coverage
on:
push:
branches: ["main"]
paths-ignore:
- "**.md"
- "LICENSE"
pull_request:
branches: [ "main" ]
paths-ignore:
- "**.md"
- "LICENSE"

jobs:
windows:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ __pycache__
*.lib
.cache/
small2.mp4
small2.avi
test/models/
*.dylib
CMakeUserPresets*
Expand Down
3 changes: 3 additions & 0 deletions packages/dartcv/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
* add `VideoCapture.grabAsync`
* add `Mat.fromBuffer` to allow creating `Mat` from self-managed buffer
* add `copyData` parameter to `Mat.fromVec`
* remove `Mat.fromPtr`, merge it to `Mat.fromMat`
* add `Mat.atU8`, `Mat.setU8`, etc.
* remove deprecated `Mat.copyToWithMask`, `List<Mat>.asVecMat()`

## 1.1.2

Expand Down
117 changes: 83 additions & 34 deletions packages/dartcv/lib/src/core/mat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,15 @@ class Mat extends CvStruct<cvg.Mat> {

//SECTION - Constructors

/// create a [Mat] **reference** from another [Mat] if [copy] is false,
/// otherwise a copy will be created.
factory Mat.fromMat(Mat mat, {bool copy = false, Rect? roi}) {
roi ??= Rect(0, 0, mat.cols, mat.rows);
final p = calloc<cvg.Mat>();
cvRun(() => ccore.cv_Mat_create_13(mat.ref, roi!.ref, p, ffi.nullptr));
cvRun(
() => roi == null
? ccore.cv_Mat_create_11(mat.ref, mat.rows, mat.cols, mat.type.value, 0, 0, p, ffi.nullptr)
: ccore.cv_Mat_create_13(mat.ref, roi.ref, p, ffi.nullptr),
);
final dst = Mat._(p, false);
if (copy) return dst.clone();
return dst;
Expand Down Expand Up @@ -120,7 +125,7 @@ class Mat extends CvStruct<cvg.Mat> {
return Mat.fromList(rows, cols, type, flatData);
}

/// This method is different from [Mat.fromPtr], will construct from pointer directly
/// construct from pointer directly
factory Mat.fromPointer(cvg.MatPtr mat, [bool attach = true]) => Mat._(mat, attach);

factory Mat.empty() {
Expand Down Expand Up @@ -319,24 +324,6 @@ class Mat extends CvStruct<cvg.Mat> {
return mat;
}

/// this constructor is a wrapper of
/// `Mat (int rows, int cols, int type, void *data, size_t step=AUTO_STEP)`
///
/// https://docs.opencv.org/4.x/d3/d63/classcv_1_1Mat.html#a51615ebf17a64c968df0bf49b4de6a3a
factory Mat.fromPtr(
cvg.Mat m,
int rows,
int cols,
int type,
int prows,
int pcols,
) {
final p = calloc<cvg.Mat>();
cvRun(() => ccore.cv_Mat_create_11(m, rows, cols, type, prows, pcols, p, ffi.nullptr));
final mat = Mat._(p);
return mat;
}

//!SECTION Constructors

//SECTION - Properties
Expand Down Expand Up @@ -386,14 +373,43 @@ class Mat extends CvStruct<cvg.Mat> {
}

//!SECTION - Properties

//SECTION - At Set

int atU8(int i0, {int? i1, int? i2}) => i1 == null
? ccore.cv_Mat_get_u8_1(ref, i0)
: (i2 == null ? ccore.cv_Mat_get_u8_2(ref, i0, i1) : ccore.cv_Mat_get_u8_3(ref, i0, i1, i2));

int atI8(int i0, {int? i1, int? i2}) => i1 == null
? ccore.cv_Mat_get_i8_1(ref, i0)
: (i2 == null ? ccore.cv_Mat_get_i8_2(ref, i0, i1) : ccore.cv_Mat_get_i8_3(ref, i0, i1, i2));

int atU16(int i0, {int? i1, int? i2}) => i1 == null
? ccore.cv_Mat_get_u16_1(ref, i0)
: (i2 == null ? ccore.cv_Mat_get_u16_2(ref, i0, i1) : ccore.cv_Mat_get_u16_3(ref, i0, i1, i2));

int atI16(int i0, {int? i1, int? i2}) => i1 == null
? ccore.cv_Mat_get_i16_1(ref, i0)
: (i2 == null ? ccore.cv_Mat_get_i16_2(ref, i0, i1) : ccore.cv_Mat_get_i16_3(ref, i0, i1, i2));

int atI32(int i0, {int? i1, int? i2}) => i1 == null
? ccore.cv_Mat_get_i32_1(ref, i0)
: (i2 == null ? ccore.cv_Mat_get_i32_2(ref, i0, i1) : ccore.cv_Mat_get_i32_3(ref, i0, i1, i2));

double atF32(int i0, {int? i1, int? i2}) => i1 == null
? ccore.cv_Mat_get_f32_1(ref, i0)
: (i2 == null ? ccore.cv_Mat_get_f32_2(ref, i0, i1) : ccore.cv_Mat_get_f32_3(ref, i0, i1, i2));

double atF64(int i0, {int? i1, int? i2}) => i1 == null
? ccore.cv_Mat_get_f64_1(ref, i0)
: (i2 == null ? ccore.cv_Mat_get_f64_2(ref, i0, i1) : ccore.cv_Mat_get_f64_3(ref, i0, i1, i2));

/// wrapper of cv::Mat::at()
///
num atNum(int i0, int i1, [int? i2]) {
/// [mtype] : cached MatType to speedup pixel access
num atNum(int i0, int i1, {int? i2, MatType? mtype}) {
// https://github.com/opencv/opencv/blob/71d3237a093b60a27601c20e9ee6c3e52154e8b1/modules/core/include/opencv2/core/mat.inl.hpp#L968
return switch (type.depth) {
mtype ??= type;
return switch (mtype.depth) {
MatType.CV_8U => i2 == null ? (ptrAt<U8>(i0) + i1).value : ptrAt<U8>(i0, i1, i2).value,
MatType.CV_8S => i2 == null ? (ptrAt<I8>(i0) + i1).value : ptrAt<I8>(i0, i1, i2).value,
MatType.CV_16U => i2 == null ? (ptrAt<U16>(i0) + i1).value : ptrAt<U16>(i0, i1, i2).value,
Expand All @@ -409,11 +425,12 @@ class Mat extends CvStruct<cvg.Mat> {
/// Get pixel value via [row], [col], returns a view of native data
///
/// Note: No bound check under **release** mode
List<num> atPixel(int row, int col) {
List<num> atPixel(int row, int col, {MatType? mtype}) {
assert(0 <= row && row < rows, "row must be less than $rows");
assert(0 <= col && col < cols, "col must be less than $cols");

switch (type.depth) {
mtype ??= type;
switch (mtype.depth) {
case MatType.CV_8U:
return ptrAt<U8>(row, col).asTypedList(channels);
case MatType.CV_8S:
Expand Down Expand Up @@ -509,7 +526,7 @@ class Mat extends CvStruct<cvg.Mat> {
/// https://docs.opencv.org/4.x/d3/d63/classcv_1_1Mat.html#a7a6d7e3696b8b19b9dfac3f209118c40
T at<T>(int i0, int i1, [int? i2]) {
if (T == int || T == double || T == num) {
return atNum(i0, i1, i2) as T;
return atNum(i0, i1, i2: i2) as T;
} else if (isSubtype<T, CvVec>()) {
return atVec<T>(i0, i1);
} else {
Expand All @@ -520,6 +537,44 @@ class Mat extends CvStruct<cvg.Mat> {
//!SECTION At

//SECTION - Set
void setU8(int i0, int val, {int? i1, int? i2}) => i1 == null
? ccore.cv_Mat_set_u8_1(ref, i0, val)
: (i2 == null ? ccore.cv_Mat_set_u8_2(ref, i0, i1, val) : ccore.cv_Mat_set_u8_3(ref, i0, i1, i2, val));

void setI8(int i0, int val, {int? i1, int? i2}) => i1 == null
? ccore.cv_Mat_set_i8_1(ref, i0, val)
: (i2 == null ? ccore.cv_Mat_set_i8_2(ref, i0, i1, val) : ccore.cv_Mat_set_i8_3(ref, i0, i1, i2, val));

void setU16(int i0, int val, {int? i1, int? i2}) => i1 == null
? ccore.cv_Mat_set_u16_1(ref, i0, val)
: (i2 == null
? ccore.cv_Mat_set_u16_2(ref, i0, i1, val)
: ccore.cv_Mat_set_u16_3(ref, i0, i1, i2, val));

void setI16(int i0, int val, {int? i1, int? i2}) => i1 == null
? ccore.cv_Mat_set_i16_1(ref, i0, val)
: (i2 == null
? ccore.cv_Mat_set_i16_2(ref, i0, i1, val)
: ccore.cv_Mat_set_i16_3(ref, i0, i1, i2, val));

void setI32(int i0, int val, {int? i1, int? i2}) => i1 == null
? ccore.cv_Mat_set_i32_1(ref, i0, val)
: (i2 == null
? ccore.cv_Mat_set_i32_2(ref, i0, i1, val)
: ccore.cv_Mat_set_i32_3(ref, i0, i1, i2, val));

void setF32(int i0, double val, {int? i1, int? i2}) => i1 == null
? ccore.cv_Mat_set_f32_1(ref, i0, val)
: (i2 == null
? ccore.cv_Mat_set_f32_2(ref, i0, i1, val)
: ccore.cv_Mat_set_f32_3(ref, i0, i1, i2, val));

void setF64(int i0, double val, {int? i1, int? i2}) => i1 == null
? ccore.cv_Mat_set_f64_1(ref, i0, val)
: (i2 == null
? ccore.cv_Mat_set_f64_2(ref, i0, i1, val)
: ccore.cv_Mat_set_f64_3(ref, i0, i1, i2, val));

void setVec<T extends CvVec>(int row, int col, T val) {
switch (val) {
// Vec2b, Vec3b, Vec4b
Expand Down Expand Up @@ -1172,11 +1227,6 @@ class Mat extends CvStruct<cvg.Mat> {
? cvRun(() => ccore.cv_Mat_copyTo(ref, dst.ref, ffi.nullptr))
: cvRun(() => ccore.cv_Mat_copyTo_1(ref, dst.ref, mask.ref, ffi.nullptr));

@Deprecated("use copyTo instead")
void copyToWithMask(Mat dst, Mat mask) {
cvRun(() => ccore.cv_Mat_copyTo_1(ref, dst.ref, mask.ref, ffi.nullptr));
}

/// Converts an array to another data type with optional scaling.
///
/// The method converts source pixel values to the target data type.
Expand Down Expand Up @@ -1500,7 +1550,6 @@ class VecMatIterator extends VecIterator<Mat> {

extension ListMatExtension on List<Mat> {
VecMat get cvd => asVec();
@Deprecated("Use asVec() instead")
VecMat asVecMat() => asVec();

VecMat asVec() => VecMat.fromList(this);
}
55 changes: 55 additions & 0 deletions packages/dartcv/test/core/mat_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ void main() async {
expect(mat1.size, [100, 200]);
expect(mat1.at<cv.Vec3b>(0, 0), cv.Vec3b(255, 255, 255));

mat1.setVec(0, 0, cv.Vec3b(2, 4, 1));
expect(src.atVec<cv.Vec3b>(0, 0), cv.Vec3b(2, 4, 1));

final diff = mat1.subtract(src);
expect(diff.sum(), cv.Scalar.zeros);

Expand Down Expand Up @@ -620,10 +623,16 @@ array([[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]],
final ptr0 = mat.ptrAt<cv.U8>(0);
expect(ptr0.address, greaterThan(0));
expect(ptr0[0], 1);

ptr0[0] = 21;
expect(mat.at<int>(0, 0), 21);
expect(ptr0[0], 21);

mat.setU8(0, 1);
expect(mat.atU8(0), 1);
mat.setU8(0, 21, i1: 0);
expect(mat.atU8(0, i1: 0), 21);

final ptr1 = mat.ptrAt<cv.U8>(0, 0);
expect(ptr1.address, greaterThan(0));
expect(ptr1[0], 21);
Expand All @@ -639,6 +648,11 @@ array([[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]],
expect(mat.at<int>(0, 0), 21);
expect(ptr0[0], 21);

mat.setI8(0, 1);
expect(mat.atI8(0), 1);
mat.setI8(0, 21, i1: 0);
expect(mat.atI8(0, i1: 0), 21);

final ptr1 = mat.ptrAt<cv.I8>(0, 0);
expect(ptr1.address, greaterThan(0));
expect(ptr1[0], 21);
Expand All @@ -657,6 +671,11 @@ array([[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]],
expect(mat.at<int>(0, 0), 21);
expect(ptr0[0], 21);

mat.setU16(0, 1);
expect(mat.atU16(0), 1);
mat.setU16(0, 21, i1: 0);
expect(mat.atU16(0, i1: 0), 21);

final ptr1 = mat.ptrAt<cv.U16>(0, 0);
expect(ptr1.address, greaterThan(0));
expect(ptr1[0], 21);
Expand All @@ -672,6 +691,11 @@ array([[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]],
expect(mat.at<int>(0, 0), 21);
expect(ptr0[0], 21);

mat.setI16(0, 1);
expect(mat.atI16(0), 1);
mat.setI16(0, 21, i1: 0);
expect(mat.atI16(0, i1: 0), 21);

final ptr1 = mat.ptrAt<cv.I16>(0, 0);
expect(ptr1.address, greaterThan(0));
expect(ptr1[0], 21);
Expand All @@ -687,6 +711,11 @@ array([[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]],
expect(mat.at<int>(0, 0), 21);
expect(ptr0[0], 21);

mat.setI32(0, 1);
expect(mat.atI32(0), 1);
mat.setI32(0, 21, i1: 0);
expect(mat.atI32(0, i1: 0), 21);

final ptr1 = mat.ptrAt<cv.I32>(0, 0);
expect(ptr1.address, greaterThan(0));
expect(ptr1[0], 21);
Expand All @@ -702,6 +731,11 @@ array([[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]],
expect(mat.at<double>(0, 0), closeTo(21.0, 1e-6));
expect(ptr0[0], closeTo(21.0, 1e-6));

mat.setF32(0, 1);
expect(mat.atF32(0), closeTo(1.0, 1e-6));
mat.setF32(0, 21, i1: 0);
expect(mat.atF32(0, i1: 0), closeTo(21.0, 1e-6));

final ptr1 = mat.ptrAt<cv.F32>(0, 0);
expect(ptr1.address, greaterThan(0));
expect(ptr1[0], closeTo(21.0, 1e-6));
Expand All @@ -719,6 +753,11 @@ array([[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]],
expect(mat.at<double>(0, 0), closeTo(21.0, 1e-6));
expect(ptr0[0], closeTo(21.0, 1e-6));

mat.setF64(0, 1);
expect(mat.atF64(0), closeTo(1.0, 1e-6));
mat.setF64(0, 21, i1: 0);
expect(mat.atF64(0, i1: 0), closeTo(21, 1e-6));

final ptr1 = mat.ptrAt<cv.F64>(0, 0);
expect(ptr1.address, greaterThan(0));
expect(ptr1[0], closeTo(21.0, 1e-6));
Expand Down Expand Up @@ -957,6 +996,22 @@ array([[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]],
print('Mat(${mat.rows}, ${mat.cols}, ${mat.channels}).at<int>: ${sw.elapsedMilliseconds}ms');
}

{
sw.reset();
sw.start();
final mtype = mat.type;
for (var row = 0; row < mat.rows; row++) {
for (var col = 0; col < mat.cols; col++) {
mat.atNum(row, col, mtype: mtype);
// mat.atI32(row, i1: col);
// mat.atVec<cv.Vec3i>(row, col);
// mat.atPixel(row, col, mtype: mtype);
}
}
sw.stop();
print('Mat(${mat.rows}, ${mat.cols}, ${mat.channels}).atNum: ${sw.elapsedMilliseconds}ms');
}

{
var currentPix = 0;
mat.set<cv.Vec3i>(mat.rows - 1, mat.cols - 1, cv.Vec3i(241, 241, 241));
Expand Down
2 changes: 1 addition & 1 deletion packages/dartcv/test/imgproc/imgproc_async_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,6 @@ void main() async {

await drawDescription(image, intersectionArea.toInt(), " (invalid input: not convex)", cv.Point(70, 580));

await cv.imwriteAsync("test/images_out/intersections.png", image);
// await cv.imwriteAsync("test/images_out/intersections.png", image);
});
}
2 changes: 1 addition & 1 deletion packages/dartcv/test/imgproc/imgproc_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,6 @@ void main() async {

drawDescription(image, intersectionArea.toInt(), " (invalid input: not convex)", cv.Point(70, 580));

cv.imwrite("test/images_out/intersections.png", image);
// cv.imwrite("test/images_out/intersections.png", image);
});
}
Loading

0 comments on commit 266c7c5

Please sign in to comment.