Skip to content

Commit

Permalink
API Change: toList3D, more test
Browse files Browse the repository at this point in the history
  • Loading branch information
rainyl committed May 19, 2024
1 parent 403438d commit 4af53ea
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 23 deletions.
38 changes: 19 additions & 19 deletions lib/src/core/mat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Mat extends CvStruct<cvg.Mat> {
/// Mat (Size size, int type, void *data, size_t step=AUTO_STEP)
///
/// https://docs.opencv.org/4.x/d3/d63/classcv_1_1Mat.html#a9fa74fb14362d87cb183453d2441948f
factory Mat.fromList(int rows, int cols, MatType type, List data, [int step = 0]) {
factory Mat.fromList(int rows, int cols, MatType type, List<num> data, [int step = 0]) {
assert(data is List<int> || data is List<double>, "Only support List<int> or List<double>");
final p = calloc<cvg.Mat>();
// 1 copy
Expand Down Expand Up @@ -425,7 +425,7 @@ class Mat extends CvStruct<cvg.Mat> {
///
/// https://docs.opencv.org/4.x/d3/d63/classcv_1_1Mat.html#a7a6d7e3696b8b19b9dfac3f209118c40
T at<T>(int row, int col, [int? i2]) {
if (T == int || T == double) {
if (T == int || T == double || T == num) {
return atNum(row, col, i2) as T;
} else if (isSubtype<T, CvVec>()) {
return atVec<T>(row, col);
Expand Down Expand Up @@ -1282,21 +1282,21 @@ class Mat extends CvStruct<cvg.Mat> {
void release() => cvRun(() => CFFI.Mat_Release(ptr));

/// This Method converts single-channel Mat to 2D List
List<List<num>> toList() {
switch (type.depth) {
case MatType.CV_8U:
case MatType.CV_8S:
case MatType.CV_16U:
case MatType.CV_16S:
case MatType.CV_32S:
return List.generate(rows, (row) => List.generate(cols, (col) => at<int>(row, col)));
case MatType.CV_32F:
case MatType.CV_64F:
return List.generate(rows, (row) => List.generate(cols, (col) => at<double>(row, col)));
default:
throw UnsupportedError("toList() for $type is not supported!");
}
}
List<List<num>> toList() => switch (type.depth) {
MatType.CV_8U => List.generate(rows, (row) => List.generate(cols, (col) => atU8(row, col))),
MatType.CV_8S => List.generate(rows, (row) => List.generate(cols, (col) => atI8(row, col))),
MatType.CV_16U =>
List.generate(rows, (row) => List.generate(cols, (col) => atU16(row, col))),
MatType.CV_16S =>
List.generate(rows, (row) => List.generate(cols, (col) => atI16(row, col))),
MatType.CV_32S =>
List.generate(rows, (row) => List.generate(cols, (col) => atI32(row, col))),
MatType.CV_32F =>
List.generate(rows, (row) => List.generate(cols, (col) => atF32(row, col))),
MatType.CV_64F =>
List.generate(rows, (row) => List.generate(cols, (col) => atF64(row, col))),
_ => throw UnsupportedError("toList() for $type is not supported!")
};

/// Returns a 3D list of the mat, only for multi-channel mats.
/// The list is ordered as [row][col][channel].
Expand All @@ -1310,10 +1310,10 @@ class Mat extends CvStruct<cvg.Mat> {
/// final list = mat.toList3D<Vec3b, int>();
/// print(list); // [[[0, 1, 2], [3, 4, 5], [6, 7, 8]]]
/// ```
List<List<List<P>>> toList3D<T extends CvVec, P extends num>() {
List<List<List<num>>> toList3D<T extends CvVec>() {
assert(channels >= 2, "toList3D() only for channels >= 2, but this.channels=$channels");
return List.generate(
rows, (row) => List.generate(cols, (col) => at<T>(row, col).val as List<P>));
rows, (row) => List.generate(cols, (col) => at<T>(row, col).val));
}

/// Get the data pointer of the Mat, this getter will reture a view of native
Expand Down
23 changes: 20 additions & 3 deletions test/core/core_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -339,21 +339,38 @@ void main() async {
for (int channel in [1, 2, 3, 4]) {
for (var depth in depthSrc) {
final srcType = cv.MatType.makeType(depth, channel);
final src = cv.Mat.zeros(3, 3, srcType);
final src = cv.Mat.randu(3, 3, srcType, low: cv.Scalar.all(0), high: cv.Scalar.all(255));
final lutSize = switch (depth) {
cv.MatType.CV_8U || cv.MatType.CV_8S => 256,
cv.MatType.CV_16U || cv.MatType.CV_16S => 65536,
_ => throw Exception("Unsupported type"),
};
for (var lutDepth in depthLut) {
final lutType = cv.MatType.makeType(lutDepth, channel);
final lut = cv.Mat.fromScalar(1, lutSize, lutType, cv.Scalar(255, 241, 21, 0));
testOneLUT(src, lut);
// 0-1: 65536-1-0 2-3: 65536-1-1 3-4: 65536-1-2
final lutData = switch (lutDepth) {
cv.MatType.CV_32F || cv.MatType.CV_64F => List.generate(
lutSize * lutType.channels, (i) => (lutSize - (i ~/ channel) - 1).toDouble()),
_ => List.generate(lutSize * lutType.channels, (i) => lutSize - (i ~/ channel) - 1),
};
final lutInverse = cv.Mat.fromList(1, lutSize, lutType, lutData);
testOneLUT(src, lutInverse);
}
}
}
});

test('cv.LUT 1', () {
final mat = cv.imread("test/images/lenna.png", flags: cv.IMREAD_COLOR);
final src = mat.convertTo(cv.MatType.CV_16UC3, alpha: 65536.0/255.0);
final lutData = List.generate(65536 * 3, (i) => 65536 - (i ~/ 3) - 1);
final lut = cv.Mat.fromList(1, 65536, cv.MatType.CV_16UC3, lutData);
final dst = cv.LUT(src, lut);
expect(dst.isEmpty, equals(false));
expect(dst.shape, src.shape);
// cv.imwrite("lut.png", dst.convertTo(cv.MatType.CV_8UC3, alpha: 255.0/65536.0));
});

test('cv.magnitude', () {
final src1 = cv.Mat.randu(4, 4, cv.MatType.CV_32FC1);
final src2 = cv.Mat.randu(4, 4, cv.MatType.CV_32FC1);
Expand Down
2 changes: 1 addition & 1 deletion test/core/mat_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ void main() async {
mat3.rows,
(row) => List.generate(
mat3.cols, (col) => List.generate(mat3.channels, (c) => row == col && c == 0 ? 1 : 0)));
expect(mat3.toList3D<cv.Vec3b, int>(), expected3);
expect(mat3.toList3D<cv.Vec3b>(), expected3);

final mat4 = cv.Mat.ones(100, 100, cv.MatType.CV_8UC3);
expect((mat4.width, mat4.height, mat4.channels), (100, 100, 3));
Expand Down

0 comments on commit 4af53ea

Please sign in to comment.