Skip to content

Commit

Permalink
Update SubjectSegmenterOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
bensonarafat committed Sep 27, 2024
1 parent 162ca65 commit 6c1e5df
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<Subject> subjects = mask.subjects;
final List<Subject> subjects = mask.subjects ?? [];

final paint = Paint()..style = PaintingStyle.fill;

Expand All @@ -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<double> confidences = subject.confidences;
final List<double> confidences = subject.confidences ?? [];

for (int y = 0; y < subjectHeight; y++) {
for (int x = 0; y < subjectWidth; x++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class SubjectSegmenterView extends StatefulWidget {

class _SubjectSegmenterViewState extends State<SubjectSegmenterView> {
final SubjectSegmenter _segmenter = SubjectSegmenter(
options: SubjectSegmenterOptions(enableForegroundBitmap: true));
options: SubjectSegmenterOptions(enableForegroundConfidenceMask: true));
bool _canProcess = true;
bool _isBusy = false;
CustomPaint? _customPaint;
Expand Down Expand Up @@ -57,8 +57,7 @@ class _SubjectSegmenterViewState extends State<SubjectSegmenterView> {
_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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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')
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand All @@ -147,12 +148,6 @@ private void addConfidenceMask(Map<String, Object> map, FloatBuffer mask) {
}
}

private void addImageDimensions(Map<String, Object> map, MethodCall call) {
Map<String, Object> 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<SubjectSegmenterMask> processImage(InputImage inputImage) async {
final results = await _channel
.invokeMethod('vision#startSubjectSegmenter', <String, dynamic>{
Expand All @@ -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].
Expand All @@ -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]
Expand All @@ -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<double>? confidences;

/// A list of subjects detected in the image, each respresented by a [Subject] instance
final List<Subject> subjects;
final List<Subject>? 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<dynamic, dynamic> json) {
final List<dynamic> list = json['subjects'];
final List<Subject> subjects =
list.map((json) => Subject.fromJson(json)).toList();
List<Subject>? 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'],
);
}
}
Expand All @@ -162,25 +143,31 @@ class Subject {
final int subjectHeight;

/// A list of confidence values for the detected subject.
final List<double> confidences;

Subject(
{required this.startX,
required this.startY,
required this.subjectWidth,
required this.subjectHeight,
required this.confidences});
final List<double>? 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<dynamic, dynamic> 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'],
);
}
}

0 comments on commit 6c1e5df

Please sign in to comment.