Skip to content

Commit

Permalink
add cvRunAsync, cvtColorAsync, gaussianBlurAsync
Browse files Browse the repository at this point in the history
  • Loading branch information
rainyl committed Jun 22, 2024
1 parent 85a2290 commit 03ee7e6
Show file tree
Hide file tree
Showing 22 changed files with 1,153 additions and 870 deletions.
22 changes: 16 additions & 6 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,18 @@ class _MyAppState extends State<MyApp> {
gray = cv.cvtColor(im, cv.COLOR_BGR2GRAY);
blur = cv.gaussianBlur(im, (7, 7), 2, sigmaY: 2);
}
return (
cv.imencode(cv.ImageFormat.png.ext, gray),
cv.imencode(cv.ImageFormat.png.ext, blur)
);
return (cv.imencode(".png", gray), cv.imencode(".png", blur));
});

Future<(cv.Mat, cv.Mat)> heavyTaskAsync(cv.Mat im) async {
late cv.Mat gray, blur;
for (var i = 0; i < 1000; i++) {
gray = await cv.cvtColorAsync(im, cv.COLOR_BGR2GRAY);
blur = await cv.gaussianBlurAsync(im, (7, 7), 2, sigmaY: 2);
}
return (gray, blur);
}

@override
Widget build(BuildContext context) {
return MaterialApp(
Expand Down Expand Up @@ -80,9 +86,13 @@ class _MyAppState extends State<MyApp> {
final data = await DefaultAssetBundle.of(context).load("images/lenna.png");
final bytes = data.buffer.asUint8List();
// heavy computation
final (gray, blur) = await heavyTask(bytes);
// final (gray, blur) = await heavyTask(bytes);
// setState(() {
// images = [bytes, gray, blur];
// });
final (gray, blur) = await heavyTaskAsync(cv.imdecode(bytes, cv.IMREAD_COLOR));
setState(() {
images = [bytes, gray, blur];
images = [bytes, cv.imencode(".png", gray), cv.imencode(".png", blur)];
});
},
child: const Text("Process"),
Expand Down
3 changes: 3 additions & 0 deletions ffigen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ headers:
- src/core/core.h
- src/core/exception.h
- src/core/svd.h
- src/core/types.h
- src/core/vec.h
- src/core/version.h
- src/dnn/asyncarray.h
Expand All @@ -30,6 +31,7 @@ headers:
- src/highgui/highgui.h
- src/imgcodecs/imgcodecs.h
- src/imgproc/imgproc.h
- src/imgproc/imgproc_async.h
- src/objdetect/objdetect.h
- src/photo/photo.h
- src/stitching/stitching.h
Expand All @@ -52,6 +54,7 @@ headers:
- src/highgui/highgui.h
- src/imgcodecs/imgcodecs.h
- src/imgproc/imgproc.h
- src/imgproc/imgproc_async.h
- src/objdetect/objdetect.h
- src/photo/photo.h
- src/stitching/stitching.h
Expand Down
80 changes: 37 additions & 43 deletions lib/src/core/base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@

library cv;

import 'dart:async';
import 'dart:ffi' as ffi;
import 'dart:ffi';
import 'dart:io';

import 'package:equatable/equatable.dart';
import 'package:ffi/ffi.dart';

import "../opencv.g.dart" show CvStatus, CvNative;
import "../opencv.g.dart" as cvg;
import "exception.dart" show CvException;

const _libraryName = "opencv_dart";
Expand All @@ -35,6 +36,7 @@ const int CV_I32_MIN = -2147483648;
const double CV_F32_MAX = 3.4028234663852886e+38;
const double CV_F64_MAX = 1.7976931348623157e+308;

// load native library
ffi.DynamicLibrary loadNativeLibrary() {
if (Platform.isIOS) return ffi.DynamicLibrary.process();
final defaultLibPath = switch (Platform.operatingSystem) {
Expand All @@ -47,8 +49,9 @@ ffi.DynamicLibrary loadNativeLibrary() {
return ffi.DynamicLibrary.open(libPath);
}

final CFFI = CvNative(loadNativeLibrary());
final CFFI = cvg.CvNative(loadNativeLibrary());

// base structures
abstract class CvObject<T extends ffi.NativeType> implements ffi.Finalizable {}

abstract class ICvStruct<T extends ffi.Struct> extends CvObject<T> {
Expand All @@ -62,8 +65,8 @@ abstract class CvStruct<T extends ffi.Struct> extends ICvStruct<T> with Equatabl
CvStruct.fromPointer(super.ptr) : super.fromPointer();
}

void cvRun(ffi.Pointer<CvStatus> Function() func) {
final s = func();
// error handler
void throwIfFailed(ffi.Pointer<cvg.CvStatus> s) {
final code = s.ref.code;
// String err = s.ref.err.cast<Utf8>().toDartString();
final msg = s.ref.msg.cast<Utf8>().toDartString();
Expand All @@ -76,8 +79,33 @@ void cvRun(ffi.Pointer<CvStatus> Function() func) {
}
}

R cvRunArena<R>(R Function(Arena arena) computation,
[Allocator wrappedAllocator = calloc, bool keep = false]) {
// sync runner
void cvRun(ffi.Pointer<cvg.CvStatus> Function() func) => throwIfFailed(func());

// async runner
typedef VoidPtr = ffi.Pointer<ffi.Void>;
Future<T> cvRunAsync<T>(
ffi.Pointer<cvg.CvStatus> Function(cvg.CvCallback_1 callback) func,
void Function(Completer<T> completer, VoidPtr p) onComplete,
) {
final completer = Completer<T>();
late final NativeCallable<cvg.CvCallback_1Function> ccallback;
void onResponse(VoidPtr p) {
onComplete(completer, p);
ccallback.close();
}

ccallback = ffi.NativeCallable.listener(onResponse);
throwIfFailed(func(ccallback.nativeFunction));
return completer.future;
}

// Arena wrapper
R cvRunArena<R>(
R Function(Arena arena) computation, [
Allocator wrappedAllocator = calloc,
bool keep = false,
]) {
final arena = Arena(wrappedAllocator);
bool isAsync = false;
try {
Expand All @@ -94,12 +122,14 @@ R cvRunArena<R>(R Function(Arena arena) computation,
}
}

// finalizers
typedef NativeFinalizerFunctionT<T extends ffi.NativeType>
= ffi.Pointer<ffi.NativeFunction<ffi.Void Function(T token)>>;

ffi.NativeFinalizer OcvFinalizer<T extends ffi.NativeType>(NativeFinalizerFunctionT<T> func) =>
ffi.NativeFinalizer(func.cast<ffi.NativeFinalizerFunction>());

// native types
typedef U8 = ffi.UnsignedChar;
typedef I8 = ffi.Char;
typedef U16 = ffi.UnsignedShort;
Expand All @@ -109,43 +139,7 @@ typedef I32 = ffi.Int;
typedef F32 = ffi.Float;
typedef F64 = ffi.Double;

// others
extension PointerCharExtension on ffi.Pointer<ffi.Char> {
String toDartString() => cast<Utf8>().toDartString();
}

enum ImageFormat {
// Windows bitmaps - *.bmp, *.dib (always supported)
bmp(ext: ".bmp"),
dib(ext: ".dib"),
// JPEG files - *.jpeg, *.jpg, *.jpe (see the Note section)
jpg(ext: ".jpg"),
jpeg(ext: ".jpeg"),
jpe(ext: ".jpe"),
// JPEG 2000 files - *.jp2 (see the Note section)
jp2(ext: ".jp2"),
// Portable Network Graphics - *.png (see the Note section)
png(ext: ".png"),
// WebP - *.webp (see the Note section)
webp(ext: ".webp"),
// Portable image format - *.pbm, *.pgm, *.ppm *.pxm, *.pnm (always supported)
pbm(ext: ".pbm"),
pgm(ext: ".pgm"),
ppm(ext: ".ppm"),
pxm(ext: ".pxm"),
pnm(ext: ".pnm"),
// Sun rasters - *.sr, *.ras (always supported)
sr(ext: ".sr"),
ras(ext: ".ras"),
// TIFF files - *.tiff, *.tif (see the Note section)
tiff(ext: ".tiff"),
tif(ext: ".tif"),
// OpenEXR Image files - *.exr (see the Note section)
exr(ext: ".exr"),
// Radiance HDR - *.hdr, *.pic (always supported)
hdr(ext: ".hdr"),
pic(ext: ".pic");
// Raster and Vector geospatial data supported by GDAL (see the Note section)

const ImageFormat({required this.ext});
final String ext;
}
2 changes: 1 addition & 1 deletion lib/src/core/mat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class Mat extends CvStruct<cvg.Mat> {

factory Mat.empty() {
final p = calloc<cvg.Mat>();
cvRun(() => CFFI.Mat_New(p, ffi.nullptr));
cvRun(() => CFFI.Mat_New(p));
final mat = Mat._(p);
return mat;
}
Expand Down
24 changes: 12 additions & 12 deletions lib/src/gapi/gcomputation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,18 @@ class GComputation extends CvStruct<cvg.GComputation> {
return GComputation.fromPointer(p);
}

Future<Mat> apply(Mat inMat) async {
final completer = Completer<Mat>();
late final NativeCallable<cvg.MatCallbackFunction> callback;
void onResponse(cvg.MatPtr p) {
completer.complete(Mat.fromPointer(p));
callback.close();
}

callback = ffi.NativeCallable.listener(onResponse);
cvRun(() => CFFI.gapi_GComputation_apply(ref, inMat.ref, callback.nativeFunction));
return completer.future;
}
// Future<Mat> apply(Mat inMat) async {
// final completer = Completer<Mat>();
// late final NativeCallable<cvg.MatCallbackFunction> callback;
// void onResponse(cvg.MatPtr p) {
// completer.complete(Mat.fromPointer(p));
// callback.close();
// }

// callback = ffi.NativeCallable.listener(onResponse);
// cvRun(() => CFFI.gapi_GComputation_apply(ref, inMat.ref, callback.nativeFunction));
// return completer.future;
// }

// Mat applyMIMO(Mat inMat) => apply(inMat);

Expand Down
23 changes: 23 additions & 0 deletions lib/src/imgproc/imgproc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

library cv;

import 'dart:async';
import 'dart:ffi' as ffi;
import 'dart:ffi';

import 'package:ffi/ffi.dart';

Expand Down Expand Up @@ -75,6 +77,11 @@ Mat cvtColor(Mat src, int code, {Mat? dst}) {
return dst;
}

Future<Mat> cvtColorAsync(Mat src, int code, {Mat? dst}) async => cvRunAsync<Mat>(
(callback) => CFFI.CvtColor_Async(src.ref, code, callback),
(completer, p) => completer.complete(Mat.fromPointer(p.cast())),
);

/// EqualizeHist Equalizes the histogram of a grayscale image.
///
/// For further details, please see:
Expand Down Expand Up @@ -571,6 +578,22 @@ Mat gaussianBlur(
return dst;
}

Future<Mat> gaussianBlurAsync(
Mat src,
Size ksize,
double sigmaX, {
Mat? dst,
double sigmaY = 0,
int borderType = BORDER_DEFAULT,
}) async =>
using<Future<Mat>>(
(arena) => cvRunAsync(
(callback) =>
CFFI.GaussianBlur_Async(src.ref, ksize.toSize(arena).ref, sigmaX, sigmaY, borderType, callback),
(completer, p) => completer.complete(Mat.fromPointer(p.cast())),
),
);

/// GetGaussianKernel returns Gaussian filter coefficients.
///
/// For further details, please see:
Expand Down
Loading

0 comments on commit 03ee7e6

Please sign in to comment.