Skip to content

Commit c5dc62c

Browse files
add face detection example
1 parent 2fbbe59 commit c5dc62c

File tree

3 files changed

+137
-6
lines changed

3 files changed

+137
-6
lines changed

example/lib/main_face.dart

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import 'package:camera/camera.dart';
2+
import 'package:firebase_ml_vision/firebase_ml_vision.dart';
3+
import 'package:flutter/material.dart';
4+
import 'package:flutter_camera_ml_vision/flutter_camera_ml_vision.dart';
5+
6+
void main() => runApp(MyApp());
7+
8+
class MyApp extends StatelessWidget {
9+
@override
10+
Widget build(BuildContext context) {
11+
return MaterialApp(
12+
title: 'Flutter Demo',
13+
theme: ThemeData(
14+
primarySwatch: Colors.blue,
15+
),
16+
home: MyHomePage(title: 'Flutter Demo Home Page'),
17+
);
18+
}
19+
}
20+
21+
class MyHomePage extends StatefulWidget {
22+
MyHomePage({Key key, this.title}) : super(key: key);
23+
24+
final String title;
25+
26+
@override
27+
_MyHomePageState createState() => _MyHomePageState();
28+
}
29+
30+
class _MyHomePageState extends State<MyHomePage> {
31+
List<Face> _faces = [];
32+
final _scanKey = GlobalKey<CameraMlVisionState>();
33+
CameraLensDirection cameraLensDirection = CameraLensDirection.front;
34+
35+
@override
36+
Widget build(BuildContext context) {
37+
return Scaffold(
38+
appBar: AppBar(
39+
title: Text(widget.title),
40+
),
41+
body: SizedBox.expand(
42+
child: CameraMlVision<List<Face>>(
43+
key: _scanKey,
44+
cameraLensDirection: cameraLensDirection,
45+
detector: FirebaseVision.instance
46+
.faceDetector(FaceDetectorOptions(
47+
enableTracking: true,
48+
mode: FaceDetectorMode.accurate,
49+
))
50+
.processImage,
51+
overlayBuilder: (c) {
52+
return CustomPaint(
53+
painter: FaceDetectorPainter(
54+
_scanKey.currentState.cameraValue.previewSize.flipped, _faces,
55+
reflection: cameraLensDirection == CameraLensDirection.front),
56+
);
57+
},
58+
onResult: (faces) {
59+
if (faces == null || faces.isEmpty || !mounted) {
60+
return;
61+
}
62+
setState(() {
63+
_faces = []..addAll(faces);
64+
});
65+
},
66+
),
67+
),
68+
);
69+
}
70+
}
71+
72+
class FaceDetectorPainter extends CustomPainter {
73+
FaceDetectorPainter(this.imageSize, this.faces, {this.reflection = false});
74+
75+
final bool reflection;
76+
final Size imageSize;
77+
final List<Face> faces;
78+
79+
@override
80+
void paint(Canvas canvas, Size size) {
81+
final Paint paint = Paint()
82+
..style = PaintingStyle.stroke
83+
..strokeWidth = 2.0
84+
..color = Colors.red;
85+
86+
for (Face face in faces) {
87+
final faceRect =
88+
_reflectionRect(reflection, face.boundingBox, imageSize.width);
89+
canvas.drawRect(
90+
_scaleRect(
91+
rect: faceRect,
92+
imageSize: imageSize,
93+
widgetSize: size,
94+
),
95+
paint,
96+
);
97+
}
98+
}
99+
100+
@override
101+
bool shouldRepaint(FaceDetectorPainter oldDelegate) {
102+
return oldDelegate.imageSize != imageSize || oldDelegate.faces != faces;
103+
}
104+
}
105+
106+
Rect _reflectionRect(bool reflection, Rect boundingBox, double width) {
107+
if (!reflection) {
108+
return boundingBox;
109+
}
110+
final centerX = width / 2;
111+
final left = ((boundingBox.left - centerX) * -1) + centerX;
112+
final right = ((boundingBox.right - centerX) * -1) + centerX;
113+
return Rect.fromLTRB(left, boundingBox.top, right, boundingBox.bottom);
114+
}
115+
116+
Rect _scaleRect({
117+
@required Rect rect,
118+
@required Size imageSize,
119+
@required Size widgetSize,
120+
}) {
121+
final scaleX = widgetSize.width / imageSize.width;
122+
final scaleY = widgetSize.height / imageSize.height;
123+
124+
final scaledRect = Rect.fromLTRB(
125+
rect.left.toDouble() * scaleX,
126+
rect.top.toDouble() * scaleY,
127+
rect.right.toDouble() * scaleX,
128+
rect.bottom.toDouble() * scaleY,
129+
);
130+
return scaledRect;
131+
}

example/pubspec.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ packages:
77
name: async
88
url: "https://pub.dartlang.org"
99
source: hosted
10-
version: "2.1.0"
10+
version: "2.2.0"
1111
boolean_selector:
1212
dependency: transitive
1313
description:
@@ -115,7 +115,7 @@ packages:
115115
name: quiver
116116
url: "https://pub.dartlang.org"
117117
source: hosted
118-
version: "2.0.2"
118+
version: "2.0.3"
119119
sky_engine:
120120
dependency: transitive
121121
description: flutter
@@ -162,7 +162,7 @@ packages:
162162
name: test_api
163163
url: "https://pub.dartlang.org"
164164
source: hosted
165-
version: "0.2.4"
165+
version: "0.2.5"
166166
typed_data:
167167
dependency: transitive
168168
description:

pubspec.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ packages:
77
name: async
88
url: "https://pub.dartlang.org"
99
source: hosted
10-
version: "2.1.0"
10+
version: "2.2.0"
1111
boolean_selector:
1212
dependency: transitive
1313
description:
@@ -101,7 +101,7 @@ packages:
101101
name: quiver
102102
url: "https://pub.dartlang.org"
103103
source: hosted
104-
version: "2.0.2"
104+
version: "2.0.3"
105105
sky_engine:
106106
dependency: transitive
107107
description: flutter
@@ -148,7 +148,7 @@ packages:
148148
name: test_api
149149
url: "https://pub.dartlang.org"
150150
source: hosted
151-
version: "0.2.4"
151+
version: "0.2.5"
152152
typed_data:
153153
dependency: transitive
154154
description:

0 commit comments

Comments
 (0)