1
1
package com .google_mlkit_subject_segmentation ;
2
2
3
3
import android .content .Context ;
4
+ import android .graphics .Bitmap ;
4
5
5
6
import androidx .annotation .NonNull ;
6
7
7
8
import com .google .mlkit .vision .common .InputImage ;
8
9
import com .google .mlkit .vision .segmentation .subject .Subject ;
9
10
import com .google .mlkit .vision .segmentation .subject .SubjectSegmentation ;
11
+ import com .google .mlkit .vision .segmentation .subject .SubjectSegmentationResult ;
10
12
import com .google .mlkit .vision .segmentation .subject .SubjectSegmenter ;
11
13
14
+ import java .io .ByteArrayInputStream ;
15
+ import java .io .ByteArrayOutputStream ;
16
+ import java .io .IOException ;
17
+ import java .io .OutputStream ;
18
+ import java .lang .reflect .Method ;
12
19
import java .util .ArrayList ;
13
20
import java .util .List ;
14
21
import java .nio .FloatBuffer ;
15
22
import java .util .HashMap ;
16
23
import java .util .Map ;
24
+ import java .util .Objects ;
17
25
18
26
import io .flutter .Log ;
19
27
import io .flutter .plugin .common .MethodCall ;
@@ -27,8 +35,6 @@ public class SubjectSegmenterProcess implements MethodChannel.MethodCallHandler
27
35
private static final String CLOSE = "vision#closeSubjectSegmenter" ;
28
36
29
37
private final Context context ;
30
-
31
- private static final String TAG = "Logger" ;
32
38
33
39
private int imageWidth ;
34
40
private int imageHeight ;
@@ -55,55 +61,119 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
55
61
}
56
62
}
57
63
58
- private SubjectSegmenter initialize (MethodCall call ) {
59
- SubjectSegmenterOptions .Builder builder = new SubjectSegmenterOptions .Builder ()
60
- .enableMultipleSubjects (new SubjectSegmenterOptions .SubjectResultOptions .Builder ()
61
- .enableConfidenceMask ().build ());
62
- SubjectSegmenterOptions options = builder .build ();
63
- return SubjectSegmentation .getClient (options );
64
- }
65
-
66
- private void handleDetection (MethodCall call , MethodChannel .Result result ){
67
- Map <String , Object > imageData = (Map <String , Object >) call .argument ("imageData" );
68
- InputImage inputImage = InputImageConverter .getInputImageFromData (imageData , context , result );
69
- if (inputImage == null ) return ;
64
+ private void handleDetection (MethodCall call , MethodChannel .Result result ) {
65
+ InputImage inputImage = InputImageConverter .getInputImageFromData (call .argument ("imageData" ), context , result );
66
+ if (inputImage == null ) return ;
70
67
imageHeight = inputImage .getHeight ();
71
68
imageWidth = inputImage .getWidth ();
69
+
72
70
String id = call .argument ("id" );
73
- SubjectSegmenter subjectSegmenter = instances .get (id );
74
- if (subjectSegmenter == null ) {
75
- subjectSegmenter = initialize (call );
76
- instances .put (id , subjectSegmenter );
71
+ SubjectSegmenter subjectSegmenter = getOrCreateSegmenter (id , call );
72
+
73
+ subjectSegmenter .process (inputImage )
74
+ .addOnSuccessListener (subjectSegmentationResult -> processResult (subjectSegmentationResult , call , result ))
75
+ .addOnFailureListener (e -> result .error ("Subject segmentation failure!" , e .getMessage (), e ));
76
+
77
+ }
78
+
79
+ private SubjectSegmenter getOrCreateSegmenter (String id , MethodCall call ) {
80
+ return instances .computeIfAbsent (id , k -> initialize (call ));
81
+ }
82
+ private SubjectSegmenter initialize (MethodCall call ) {
83
+ Map <String , Object > options = call .argument ("options" );
84
+ SubjectSegmenterOptions .Builder builder = new SubjectSegmenterOptions .Builder ();
85
+ assert options != null ;
86
+ configureBuilder (builder , options );
87
+ return SubjectSegmentation .getClient (builder .build ());
88
+ }
89
+
90
+ private void configureBuilder (SubjectSegmenterOptions .Builder builder , Map <String , Object > options ) {
91
+ if (Boolean .TRUE .equals (options .get ("enableForegroundBitmap" ))){
92
+ builder .enableForegroundBitmap ();
93
+ }
94
+ if (Boolean .TRUE .equals (options .get ("enableForegroundConfidenceMask" ))){
95
+ builder .enableForegroundConfidenceMask ();
77
96
}
97
+ configureMultipleSubjects (builder , options );
98
+ }
99
+
100
+ private void configureMultipleSubjects (SubjectSegmenterOptions .Builder builder , Map <String , Object > options ) {
101
+ boolean enableMultiConfidenceMask = Boolean .TRUE .equals (options .get ("enableMultiConfidenceMask" )) ;
102
+ boolean enableMultiSubjectBitmap = Boolean .TRUE .equals (options .get ("enableMultiSubjectBitmap" ));
103
+
104
+ if (enableMultiConfidenceMask || enableMultiSubjectBitmap ) {
105
+ SubjectSegmenterOptions .SubjectResultOptions .Builder subjectBuilder = new SubjectSegmenterOptions .SubjectResultOptions .Builder ();
106
+ if (enableMultiConfidenceMask ) subjectBuilder .enableConfidenceMask ();
107
+ if (enableMultiSubjectBitmap ) subjectBuilder .enableSubjectBitmap ();
108
+ builder .enableMultipleSubjects (subjectBuilder .build ());
109
+ }
110
+ }
111
+
112
+ private void processResult (SubjectSegmentationResult subjectSegmentationResult , MethodCall call , MethodChannel .Result result ) {
113
+ Map <String , Object > resultMap = new HashMap <>();
114
+ Map <String , Object > options = call .argument ("options" );
115
+
116
+ assert options != null ;
117
+ if (Boolean .TRUE .equals (options .get ("enableForegroundBitmap" ))) {
118
+ addForegroundBitmap (resultMap , subjectSegmentationResult .getForegroundBitmap ());
119
+ }
120
+
121
+ if (Boolean .TRUE .equals (options .get ("enableForegroundConfidenceMask" ))){
122
+ addConfidenceMask (resultMap , subjectSegmentationResult .getForegroundConfidenceMask ());
123
+ }
124
+ if (Boolean .TRUE .equals (options .get ("enableMultiConfidenceMask" )) || Boolean .TRUE .equals (options .get ("enableMultiSubjectBitmap" ))) {
78
125
79
- subjectSegmenter .process (inputImage )
80
- .addOnSuccessListener ( subjectSegmentationResult -> {
81
126
List <Map <String , Object >> subjectsData = new ArrayList <>();
82
- for (Subject subject : subjectSegmentationResult .getSubjects ()){
83
- Map <String , Object > subjectData = getStringObjectMap (subject );
127
+ for (Subject subject : subjectSegmentationResult .getSubjects ()){
128
+ Map <String , Object > subjectData = getStringObjectMap (subject , options );
84
129
subjectsData .add (subjectData );
85
130
}
86
- Map <String , Object > map = new HashMap <>();
87
- map .put ("subjects" , subjectsData );
88
- map .put ("width" , imageWidth );
89
- map .put ("height" , imageHeight );
90
- result .success (map );
91
- }).addOnFailureListener ( e -> result .error ("Subject segmentation failed!" , e .getMessage (), e ) );
131
+ resultMap .put ("subjects" , subjectsData );
132
+ }
133
+ resultMap .put ("width" , imageWidth );
134
+ resultMap .put ("height" , imageHeight );
135
+
136
+ result .success (resultMap );
137
+ }
138
+
139
+ private void addForegroundBitmap (Map <String , Object > map , Bitmap bitmap ) {
140
+ if (bitmap != null ) {
141
+ map .put ("bitmap" , getBitmapBytes (bitmap ));
142
+ }
143
+ }
144
+
145
+ private void addConfidenceMask (Map <String , Object > map , FloatBuffer mask ) {
146
+ if (mask != null ) {
147
+ map .put ("confidences" , getConfidences (mask ));
148
+ }
149
+ }
150
+
151
+ private static float [] getConfidences (FloatBuffer floatBuffer ) {
152
+ float [] confidences = new float [floatBuffer .remaining ()];
153
+ floatBuffer .get (confidences );
154
+ return confidences ;
155
+ }
156
+
157
+ private static byte [] getBitmapBytes (Bitmap bitmap ) {
158
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream ();
159
+ bitmap .compress (Bitmap .CompressFormat .PNG , 100 , outputStream );
160
+ return outputStream .toByteArray ();
92
161
}
93
162
163
+
94
164
@ NonNull
95
- private static Map <String , Object > getStringObjectMap (Subject subject ) {
165
+ private static Map <String , Object > getStringObjectMap (Subject subject , Map < String , Object > options ) {
96
166
Map <String , Object > subjectData = new HashMap <>();
97
167
subjectData .put ("startX" , subject .getStartX ());
98
168
subjectData .put ("startY" , subject .getStartY ());
99
169
subjectData .put ("width" , subject .getWidth ());
100
170
subjectData .put ("height" , subject .getHeight ());
101
-
102
- FloatBuffer confidenceMask = subject .getConfidenceMask ();
103
- assert confidenceMask != null ;
104
- float [] confidences = new float [ confidenceMask . remaining ()];
105
- confidenceMask . get ( confidences );
106
- subjectData . put ( "confidences" , confidences );
171
+ if ( Boolean . TRUE . equals ( options . get ( "enableMultiConfidenceMask" ))){
172
+ subjectData . put ( "confidences" , getConfidences ( Objects . requireNonNull ( subject .getConfidenceMask ())) );
173
+ }
174
+ if ( Boolean . TRUE . equals ( options . get ( "enableMultiSubjectBitmap" ))) {
175
+ subjectData . put ( "bitmap" , getBitmapBytes ( Objects . requireNonNull ( subject . getBitmap ())) );
176
+ }
107
177
return subjectData ;
108
178
}
109
179
0 commit comments