Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Subject Segmentation #666

Merged
merged 16 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/code-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ jobs:
working-directory: ./packages/google_mlkit_selfie_segmentation
run: flutter pub get

- name: Install dependencies for google_mlkit_subject_segmentation
working-directory: ./packages/google_mlkit_subject_segmentation
run: flutter pub get

- name: Install dependencies for example
working-directory: ./packages/example
run: flutter pub get
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Google's ML Kit for Flutter is a set of [Flutter plugins](https://flutter.io/pla
| [Digital Ink Recognition](https://developers.google.com/ml-kit/vision/digital-ink-recognition) | [google\_mlkit\_digital\_ink\_recognition](https://pub.dev/packages/google_mlkit_digital_ink_recognition) [![Pub Version](https://img.shields.io/pub/v/google_mlkit_digital_ink_recognition)](https://pub.dev/packages/google_mlkit_digital_ink_recognition) | [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/flutter-ml/google_ml_kit_flutter/tree/master/packages/google_mlkit_digital_ink_recognition) | ✅ | ✅ |
| [Pose Detection](https://developers.google.com/ml-kit/vision/pose-detection) | [google\_mlkit\_pose\_detection](https://pub.dev/packages/google_mlkit_pose_detection) [![Pub Version](https://img.shields.io/pub/v/google_mlkit_pose_detection)](https://pub.dev/packages/google_mlkit_pose_detection) | [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/flutter-ml/google_ml_kit_flutter/tree/master/packages/google_mlkit_pose_detection) | ✅ | ✅ |
| [Selfie Segmentation](https://developers.google.com/ml-kit/vision/selfie-segmentation) | [google\_mlkit\_selfie\_segmentation](https://pub.dev/packages/google_mlkit_selfie_segmentation) [![Pub Version](https://img.shields.io/pub/v/google_mlkit_selfie_segmentation)](https://pub.dev/packages/google_mlkit_selfie_segmentation) | [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/flutter-ml/google_ml_kit_flutter/tree/master/packages/google_mlkit_selfie_segmentation) | ✅ | ✅ |
| [Subject Segmentation](https://developers.google.com/ml-kit/vision/subject-segmentation) | [google\_mlkit\_subject\_segemtation](https://pub.dev/packages/google_mlkit_subject_segemtation) [![Pub Version](https://img.shields.io/pub/v/google_mlkit_subject_segemtation)](https://pub.dev/packages/google_mlkit_subject_segemtation) | [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/flutter-ml/google_ml_kit_flutter/tree/master/packages/google_mlkit_subject_segemtation) | | ❌ |
| [Subject Segmentation](https://developers.google.com/ml-kit/vision/subject-segmentation) | [google\_mlkit\_subject\_segemtation](https://pub.dev/packages/google_mlkit_subject_segemtation) [![Pub Version](https://img.shields.io/pub/v/google_mlkit_subject_segemtation)](https://pub.dev/packages/google_mlkit_subject_segemtation) | [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/flutter-ml/google_ml_kit_flutter/tree/master/packages/google_mlkit_subject_segemtation) | | ❌ |
| [Document Scanner](https://developers.google.com/ml-kit/vision/doc-scanner) | [google\_mlkit\_document\_scanner](https://pub.dev/packages/google_mlkit_document_scanner) [![Pub Version](https://img.shields.io/pub/v/google_mlkit_document_scanner)](https://pub.dev/packages/google_mlkit_document_scanner) | [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/flutter-ml/google_ml_kit_flutter/tree/master/packages/google_mlkit_document_scanner) | ✅ | ❌ |

### Natural Language APIs
Expand Down
2 changes: 1 addition & 1 deletion packages/example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ android {

defaultConfig {
applicationId "com.google.ml.kit.flutter.example"
minSdkVersion 21
minSdkVersion 24
targetSdkVersion 34
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
Expand Down
2 changes: 1 addition & 1 deletion packages/example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
</activity>
<meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="ica,ocr,face" />
android:value="ica,ocr,face,subject_segment" />
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
Expand Down
Binary file added packages/example/assets/images/child_dog.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/example/assets/images/friends.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 7 additions & 2 deletions packages/example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'dart:io';

import 'package:flutter/material.dart';

import 'nlp_detector_views/entity_extraction_view.dart';
import 'nlp_detector_views/language_identifier_view.dart';
import 'nlp_detector_views/language_translator_view.dart';
Expand All @@ -15,6 +14,7 @@ import 'vision_detector_views/label_detector_view.dart';
import 'vision_detector_views/object_detector_view.dart';
import 'vision_detector_views/pose_detector_view.dart';
import 'vision_detector_views/selfie_segmenter_view.dart';
import 'vision_detector_views/subject_segmenter_view.dart';
import 'vision_detector_views/text_detector_view.dart';

Future<void> main() async {
Expand Down Expand Up @@ -54,7 +54,9 @@ class Home extends StatelessWidget {
children: [
CustomCard('Barcode Scanning', BarcodeScannerView()),
CustomCard('Face Detection', FaceDetectorView()),
CustomCard('Face Mesh Detection', FaceMeshDetectorView()),
if (Platform.isAndroid)
CustomCard(
'Face Mesh Detection', FaceMeshDetectorView()),
CustomCard('Image Labeling', ImageLabelView()),
CustomCard('Object Detection', ObjectDetectorView()),
CustomCard('Text Recognition', TextRecognizerView()),
Expand All @@ -63,6 +65,9 @@ class Home extends StatelessWidget {
CustomCard('Selfie Segmentation', SelfieSegmenterView()),
if (Platform.isAndroid)
CustomCard('Document Scanner', DocumentScannerView()),
if (Platform.isAndroid)
CustomCard(
'Subject Segmentation', SubjectSegmenterView())
],
),
SizedBox(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:google_mlkit_subject_segmentation/google_mlkit_subject_segmentation.dart';
import 'coordinates_translator.dart';

class SubjectSegmentationPainter extends CustomPainter {
final SubjectSegmenterMask mask;
final Size imageSize;
final Color color = Colors.red;
final InputImageRotation rotation;
final CameraLensDirection cameraLensDirection;

SubjectSegmentationPainter(
this.mask,
this.imageSize,
this.rotation,
this.cameraLensDirection,
);

@override
void paint(Canvas canvas, Size size) {
final int width = mask.width;
final int height = mask.height;
final List<Subject> subjects = mask.subjects;

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

for (final Subject subject in subjects) {
final int startX = subject.startX;
final int startY = subject.startY;
final int subjectWidth = subject.subjectWidth;
final int subjectHeight = subject.subjectHeight;
final List<double> confidences = subject.confidences;

for (int y = 0; y < subjectHeight; y++) {
for (int x = 0; y < subjectWidth; x++) {
final int absoluteX = startX;
final int absoluteY = startY;

final int tx = translateX(
absoluteX.toDouble(),
size,
Size(width.toDouble(), height.toDouble()),
rotation,
cameraLensDirection)
.round();

final int ty = translateY(
absoluteY.toDouble(),
size,
Size(width.toDouble(), height.toDouble()),
rotation,
cameraLensDirection)
.round();

final double opacity = confidences[(y * subjectWidth) + x] * 0.5;
paint.color = color.withOpacity(opacity);
canvas.drawCircle(Offset(tx.toDouble(), ty.toDouble()), 2, paint);
}
}
}
}

@override
bool shouldRepaint(SubjectSegmentationPainter oldDelegate) {
return oldDelegate.mask != mask;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:google_mlkit_subject_segmentation/google_mlkit_subject_segmentation.dart';

import 'detector_view.dart';
import 'painters/subject_segmentation_painter.dart';

class SubjectSegmenterView extends StatefulWidget {
@override
State<SubjectSegmenterView> createState() => _SubjectSegmenterViewState();
}

class _SubjectSegmenterViewState extends State<SubjectSegmenterView> {
final SubjectSegmenter _segmenter = SubjectSegmenter();
bool _canProcess = true;
bool _isBusy = false;
CustomPaint? _customPaint;
String? _text;
var _cameraLensDirection = CameraLensDirection.back;

@override
void dispose() async {
_canProcess = false;
_segmenter.close();
super.dispose();
}

@override
Widget build(BuildContext context) {
return DetectorView(
title: 'Subject Segmenter',
customPaint: _customPaint,
text: _text,
onImage: _processImage,
initialCameraLensDirection: _cameraLensDirection,
onCameraLensDirectionChanged: (value) => _cameraLensDirection = value,
);
}

Future<void> _processImage(InputImage inputImage) async {
if (!_canProcess) return;
if (_isBusy) return;
_isBusy = true;
setState(() {
_text = '';
});
final SubjectSegmenterMask mask = await _segmenter.processImage(inputImage);
if (inputImage.metadata?.size != null &&
inputImage.metadata?.rotation != null) {
final painter = SubjectSegmentationPainter(
mask,
inputImage.metadata!.size,
inputImage.metadata!.rotation,
_cameraLensDirection,
);
_customPaint = CustomPaint(painter: painter);
} else {
// TODO: set _customPaint to draw on top of image
_text = 'There is a mask with ${mask.subjects.length} subjects';

_customPaint = null;
}
_isBusy = false;
if (mounted) {
setState(() {});
}
}
}
7 changes: 7 additions & 0 deletions packages/example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,13 @@ packages:
relative: true
source: path
version: "0.11.0"
google_mlkit_subject_segmentation:
dependency: "direct main"
description:
path: "../google_mlkit_subject_segmentation"
relative: true
source: path
version: "0.0.1"
google_mlkit_text_recognition:
dependency: "direct main"
description:
Expand Down
2 changes: 2 additions & 0 deletions packages/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ dependencies:
path: ../google_mlkit_pose_detection
google_mlkit_selfie_segmentation:
path: ../google_mlkit_selfie_segmentation
google_mlkit_subject_segmentation:
path: ../google_mlkit_subject_segmentation
google_mlkit_text_recognition:
path: ../google_mlkit_text_recognition

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@ android {
}

dependencies {
implementation 'com.google.mlkit:barcode-scanning:17.2.0'
implementation 'com.google.mlkit:barcode-scanning:17.3.0'
}
2 changes: 1 addition & 1 deletion packages/google_mlkit_face_detection/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@ android {
}

dependencies {
implementation 'com.google.mlkit:face-detection:16.1.6'
implementation 'com.google.mlkit:face-detection:16.1.7'
}
4 changes: 2 additions & 2 deletions packages/google_mlkit_image_labeling/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ android {
}

dependencies {
implementation 'com.google.mlkit:image-labeling:17.0.8'
implementation 'com.google.mlkit:image-labeling-custom:17.0.2'
implementation 'com.google.mlkit:image-labeling:17.0.9'
implementation 'com.google.mlkit:image-labeling-custom:17.0.3'
implementation 'com.google.mlkit:linkfirebase:17.0.0'
}
2 changes: 1 addition & 1 deletion packages/google_mlkit_language_id/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@ android {
}

dependencies {
implementation 'com.google.mlkit:language-id:17.0.5'
implementation 'com.google.mlkit:language-id:17.0.6'
}
4 changes: 2 additions & 2 deletions packages/google_mlkit_object_detection/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ android {
}

dependencies {
implementation 'com.google.mlkit:object-detection:17.0.1'
implementation 'com.google.mlkit:object-detection-custom:17.0.1'
implementation 'com.google.mlkit:object-detection:17.0.2'
implementation 'com.google.mlkit:object-detection-custom:17.0.2'
implementation 'com.google.mlkit:linkfirebase:17.0.0'
}
4 changes: 2 additions & 2 deletions packages/google_mlkit_pose_detection/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ android {
}

dependencies {
implementation 'com.google.mlkit:pose-detection:18.0.0-beta4'
implementation 'com.google.mlkit:pose-detection-accurate:18.0.0-beta4'
implementation 'com.google.mlkit:pose-detection:18.0.0-beta5'
implementation 'com.google.mlkit:pose-detection-accurate:18.0.0-beta5'
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@ android {
}

dependencies {
implementation 'com.google.mlkit:segmentation-selfie:16.0.0-beta5'
implementation 'com.google.mlkit:segmentation-selfie:16.0.0-beta6'
}
2 changes: 1 addition & 1 deletion packages/google_mlkit_smart_reply/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ android {
}

dependencies {
implementation 'com.google.mlkit:smart-reply:17.0.3'
implementation 'com.google.mlkit:smart-reply:17.0.4'
}

29 changes: 29 additions & 0 deletions packages/google_mlkit_subject_segmentation/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
**/doc/api/
.dart_tool/
build/
33 changes: 33 additions & 0 deletions packages/google_mlkit_subject_segmentation/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: "300451adae589accbece3490f4396f10bdf15e6e"
channel: "stable"

project_type: plugin

# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 300451adae589accbece3490f4396f10bdf15e6e
base_revision: 300451adae589accbece3490f4396f10bdf15e6e
- platform: android
create_revision: 300451adae589accbece3490f4396f10bdf15e6e
base_revision: 300451adae589accbece3490f4396f10bdf15e6e
- platform: ios
create_revision: 300451adae589accbece3490f4396f10bdf15e6e
base_revision: 300451adae589accbece3490f4396f10bdf15e6e

# User provided section

# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
3 changes: 3 additions & 0 deletions packages/google_mlkit_subject_segmentation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 0.0.1

* Initial release.
21 changes: 21 additions & 0 deletions packages/google_mlkit_subject_segmentation/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2022 Francisco Bernal, Bharat Biradar and Benson Arafat.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading
Loading