From 6c1e5df7008e5ae2a844f42ef76da3a4024aefee Mon Sep 17 00:00:00 2001 From: Benson Arafat Date: Fri, 27 Sep 2024 21:36:20 +0100 Subject: [PATCH] Update SubjectSegmenterOptions --- .../subject_segmentation_painter.dart | 4 +- .../subject_segmenter_view.dart | 5 +- .../android/build.gradle | 2 +- .../SubjectSegmenterProcess.java | 15 +-- .../lib/src/subject_segmenter.dart | 115 ++++++++---------- 5 files changed, 61 insertions(+), 80 deletions(-) diff --git a/packages/example/lib/vision_detector_views/painters/subject_segmentation_painter.dart b/packages/example/lib/vision_detector_views/painters/subject_segmentation_painter.dart index 5f801165..78023c99 100644 --- a/packages/example/lib/vision_detector_views/painters/subject_segmentation_painter.dart +++ b/packages/example/lib/vision_detector_views/painters/subject_segmentation_painter.dart @@ -21,7 +21,7 @@ class SubjectSegmentationPainter extends CustomPainter { void paint(Canvas canvas, Size size) { final int width = mask.width; final int height = mask.height; - final List subjects = mask.subjects; + final List subjects = mask.subjects ?? []; final paint = Paint()..style = PaintingStyle.fill; @@ -30,7 +30,7 @@ class SubjectSegmentationPainter extends CustomPainter { final int startY = subject.startY; final int subjectWidth = subject.subjectWidth; final int subjectHeight = subject.subjectHeight; - final List confidences = subject.confidences; + final List confidences = subject.confidences ?? []; for (int y = 0; y < subjectHeight; y++) { for (int x = 0; y < subjectWidth; x++) { diff --git a/packages/example/lib/vision_detector_views/subject_segmenter_view.dart b/packages/example/lib/vision_detector_views/subject_segmenter_view.dart index 9e50a0a7..4977e65d 100644 --- a/packages/example/lib/vision_detector_views/subject_segmenter_view.dart +++ b/packages/example/lib/vision_detector_views/subject_segmenter_view.dart @@ -12,7 +12,7 @@ class SubjectSegmenterView extends StatefulWidget { class _SubjectSegmenterViewState extends State { final SubjectSegmenter _segmenter = SubjectSegmenter( - options: SubjectSegmenterOptions(enableForegroundBitmap: true)); + options: SubjectSegmenterOptions(enableForegroundConfidenceMask: true)); bool _canProcess = true; bool _isBusy = false; CustomPaint? _customPaint; @@ -57,8 +57,7 @@ class _SubjectSegmenterViewState extends State { _customPaint = CustomPaint(painter: painter); } else { // TODO: set _customPaint to draw on top of image - _text = 'There is a mask with ${mask.subjects.length} subjects'; - + _text = 'There is a mask with ${mask.subjects?.length} subjects'; _customPaint = null; } _isBusy = false; diff --git a/packages/google_mlkit_subject_segmentation/android/build.gradle b/packages/google_mlkit_subject_segmentation/android/build.gradle index d32869c8..ddb79afb 100644 --- a/packages/google_mlkit_subject_segmentation/android/build.gradle +++ b/packages/google_mlkit_subject_segmentation/android/build.gradle @@ -41,5 +41,5 @@ android { dependencies { implementation 'com.google.android.gms:play-services-mlkit-subject-segmentation:16.0.0-beta1' - implementation files('/Users/bensonarafat/development/flutter/bin/cache/artifacts/engine/android-arm/flutter.jar') +// implementation files('/Users/bensonarafat/development/flutter/bin/cache/artifacts/engine/android-arm/flutter.jar') } diff --git a/packages/google_mlkit_subject_segmentation/android/src/main/java/com/google_mlkit_subject_segmentation/SubjectSegmenterProcess.java b/packages/google_mlkit_subject_segmentation/android/src/main/java/com/google_mlkit_subject_segmentation/SubjectSegmenterProcess.java index 10e8c94d..eee52a71 100644 --- a/packages/google_mlkit_subject_segmentation/android/src/main/java/com/google_mlkit_subject_segmentation/SubjectSegmenterProcess.java +++ b/packages/google_mlkit_subject_segmentation/android/src/main/java/com/google_mlkit_subject_segmentation/SubjectSegmenterProcess.java @@ -35,8 +35,6 @@ public class SubjectSegmenterProcess implements MethodChannel.MethodCallHandler private static final String CLOSE = "vision#closeSubjectSegmenter"; private final Context context; - - private static final String TAG = "Logger"; private int imageWidth; private int imageHeight; @@ -64,8 +62,10 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result } private void handleDetection(MethodCall call, MethodChannel.Result result) { - InputImage inputImage = InputImageConverter.getInputImageFromData(call.argument("imageDate"), context, result); + InputImage inputImage = InputImageConverter.getInputImageFromData(call.argument("imageData"), context, result); if(inputImage == null) return; + imageHeight = inputImage.getHeight(); + imageWidth = inputImage.getWidth(); String id = call.argument("id"); SubjectSegmenter subjectSegmenter = getOrCreateSegmenter(id, call); @@ -130,7 +130,8 @@ private void processResult(SubjectSegmentationResult subjectSegmentationResult, } resultMap.put("subjects", subjectsData); } - addImageDimensions(resultMap, call); + resultMap.put("width", imageWidth); + resultMap.put("height", imageHeight); result.success(resultMap); } @@ -147,12 +148,6 @@ private void addConfidenceMask(Map map, FloatBuffer mask) { } } - private void addImageDimensions(Map map, MethodCall call) { - Map imageData = call.argument("imageData"); - assert imageData != null; - map.put("width", imageData.get("width")); - map.put("height", imageData.get("height")); - } private static float[] getConfidences(FloatBuffer floatBuffer) { float[] confidences = new float[floatBuffer.remaining()]; floatBuffer.get(confidences); diff --git a/packages/google_mlkit_subject_segmentation/lib/src/subject_segmenter.dart b/packages/google_mlkit_subject_segmentation/lib/src/subject_segmenter.dart index 41f6778d..07ca2d94 100644 --- a/packages/google_mlkit_subject_segmentation/lib/src/subject_segmenter.dart +++ b/packages/google_mlkit_subject_segmentation/lib/src/subject_segmenter.dart @@ -17,13 +17,13 @@ class SubjectSegmenter { /// The options for the subject segmenter final SubjectSegmenterOptions options; - /// Constructor to create an instance of [FaceDetector]. + /// Constructor to create an instance of [SubjectSegmention]. SubjectSegmenter({required this.options}); /// Processes the given [InputImage] for segmentation. /// /// Sends the [InputImage] data to the natvie platform via the method channel - /// Returns the segmentation mask in the given image or nil if there was an error. + /// Returns the segmentation mask in the given image. Future processImage(InputImage inputImage) async { final results = await _channel .invokeMethod('vision#startSubjectSegmenter', { @@ -44,45 +44,36 @@ class SubjectSegmenter { _channel.invokeMethod('vision#closeSubjectSegmenter', {'id': id}); } -/// Immutable options for configuring features of [FaceDetector]. +/// Immutable options for configuring features of [SubjectSegmention]. /// -/// Used to configure features such as classification, face tracking, speed, -/// etc. +/// Used to configure features such as foreground confidence mask, foreground bitmap, multi confidence mask +/// or multi subject bitmap class SubjectSegmenterOptions { - /// Constructor for [FaceDetectorOptions]. + /// Constructor for [SubjectSegmenterOptions]. /// - /// The parameter [minFaceSize] must be between 0.0 and 1.0, inclusive. + /// The parameter to enable options + /// NOTE: To improve memory efficiency, it is recommended to only enable the necessary options. SubjectSegmenterOptions({ - this.enableForegroundConfidenceMask = false, + this.enableForegroundConfidenceMask = true, this.enableForegroundBitmap = false, this.enableMultiConfidenceMask = false, this.enableMultiSubjectBitmap = false, - }) : assert( - (enableForegroundConfidenceMask ? 1 : 0) + - (enableForegroundBitmap ? 1 : 0) + - (enableMultiConfidenceMask ? 1 : 0) + - (enableMultiSubjectBitmap ? 1 : 0) == - 1, - 'Exactly one option must be true'); + }); /// - /// TODO: Comment here - /// + /// Enables foreground confidence mask. final bool enableForegroundConfidenceMask; /// - /// TODO: comment here - /// + /// Enables foreground bitmap final bool enableForegroundBitmap; /// - /// TODO: Comment here - /// + /// Enables confidence mask for segmented Subjects final bool enableMultiConfidenceMask; /// - /// - /// + /// Enables subject bitmap for segmented Subjects. final bool enableMultiSubjectBitmap; /// Returns a json representation of an instance of [SubjectSegmenterOptions]. @@ -92,25 +83,6 @@ class SubjectSegmenterOptions { 'enableMultiConfidenceMask': enableMultiConfidenceMask, 'enableMultiSubjectBitmap': enableMultiSubjectBitmap, }; - - // Factory constructor to ensure one option is selected if none are provided - factory SubjectSegmenterOptions.withDefaultOption() { - return SubjectSegmenterOptions(enableForegroundConfidenceMask: true); - } - - // Method to validate options - static bool areOptionsValid({ - bool enableForegroundConfidenceMask = false, - bool enableForegroundBitmap = false, - bool enableMultiConfidenceMask = false, - bool enableMultiSubjectBitmap = false, - }) { - return (enableForegroundConfidenceMask ? 1 : 0) + - (enableForegroundBitmap ? 1 : 0) + - (enableMultiConfidenceMask ? 1 : 0) + - (enableMultiSubjectBitmap ? 1 : 0) == - 1; - } } /// A data class that represents the segmentation mask returned by the [SubjectSegmenterMask] @@ -121,28 +93,37 @@ class SubjectSegmenterMask { /// The height of the segmentation mask final int height; + /// The masked bitmap for the input image + final Uint8List? bitmap; + + /// A list of forground confidence mask for the input image + final List? confidences; + /// A list of subjects detected in the image, each respresented by a [Subject] instance - final List subjects; + final List? subjects; /// Constructor to create a instance of [SubjectSegmenterMask]. - /// - /// The [width] and [height] represent the dimensions of the mark, - /// and [subjects] is a list of detected subjects SubjectSegmenterMask({ required this.width, required this.height, - required this.subjects, + this.subjects, + this.bitmap, + this.confidences, }); /// Returns an instance of [SubjectSegmenterMask] from json factory SubjectSegmenterMask.fromJson(Map json) { - final List list = json['subjects']; - final List subjects = - list.map((json) => Subject.fromJson(json)).toList(); + List? subjects; + if (json['subjects'] != null) { + subjects = + json['subjects'].map((json) => Subject.fromJson(json)).toList(); + } return SubjectSegmenterMask( width: json['width'] as int, height: json['height'] as int, subjects: subjects, + confidences: json['confidences'], + bitmap: json['bitmap'], ); } } @@ -162,25 +143,31 @@ class Subject { final int subjectHeight; /// A list of confidence values for the detected subject. - final List confidences; - - Subject( - {required this.startX, - required this.startY, - required this.subjectWidth, - required this.subjectHeight, - required this.confidences}); + final List? confidences; + + /// The masked bitmap of the subject + final Uint8List? bitmap; + + Subject({ + required this.startX, + required this.startY, + required this.subjectWidth, + required this.subjectHeight, + this.confidences, + this.bitmap, + }); /// Creates an instance of [Subject] from a JSON object. /// /// This factory constructor is used to convert JSON data into a [Subject] object. - factory Subject.fromJson(Map json) { return Subject( - startX: json['startX'] as int, - startY: json['startY'] as int, - subjectWidth: json['width'] as int, - subjectHeight: json['height'] as int, - confidences: json['confidences']); + startX: json['startX'] as int, + startY: json['startY'] as int, + subjectWidth: json['width'] as int, + subjectHeight: json['height'] as int, + confidences: json['confidences'], + bitmap: json['bitmap'], + ); } }