如今在Covid的情况下,戴口罩保护自己和他人非常重要。所以这个应用程序有助于检测这个人是否戴过口罩。在这个应用程序中,掩码检测是在 TensorFlow Lite 的帮助下完成的。
按照步骤在我们的Flutter应用程序中实现掩码检测
- 将依赖项添加到pubspec.yaml文件。
- 将依赖项导入到 main.js 中。dart文件
第 1 步:首先在您的 pubspec.yaml 文件中添加以下依赖项
在pubspec.yaml文件中添加给定的依赖项
Dart
dependencies:
cupertino_icons: ^1.0.2
image_picker: ^0.7.4
tflite:
google_fonts:
Dart
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
// Material App
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
brightness: Brightness.dark,
primaryColor: Color(0xff01AEBC),
),
// Main Screen in our app
home: HomePage(),
);
}
}
Dart
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State {
// Variables Declared
bool _loading = true;
File _image;
final imagePicker = ImagePicker();
List _predictions = [];
// Methods to pick the image from Camera and Gallery
Future loadImageGallery() async {
final image = await imagePicker.getImage(source: ImageSource.gallery);
detectImage(image);
}
Future loadImageCamera() async {
final image = await imagePicker.getImage(source: ImageSource.camera);
detectImage(image);
}
Dart
//Initialize the state
@override
void initState() {
// TODO: implement initState
super.initState();
loadModel();
}
// Added extracted files in loadModel() function
loadModel() async{
Tflite.close();
await Tflite.loadModel(model: 'assets/model_unquant.tflite',
labels: 'assets/labels.txt');
}
// Created detectImage() for detecting the image
Future detectImage(image) async {
var prediction = await Tflite.runModelOnImage(
path: image.path,
numResults: 2,
threshold: 0.6,
imageMean: 127.5,
imageStd: 127.5,
);
setState(() {
_loading = false;
if (image != null) {
_image = File(image.path);
_predictions = prediction;
} else {
print('No image selected.');
}
});
}
// Ended the function
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
Dart
@override
Widget build(BuildContext context) {
return Scaffold(
// Appbar declared
appBar: AppBar(
title: Text('Mask Detection',
style: GoogleFonts.robotoCondensed(),
),
),
body: SingleChildScrollView(
// Column containing images and buttons
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// Image will display here
_loading == false ? Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
child: Column(
children: [
Container(
height: 280,
width: 220,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Image.file(_image)),
),
SizedBox(height: 10),
Text(_predictions[0]['label'].toString().substring(2),
style: GoogleFonts.robotoCondensed(
fontSize: 20,
),
),
SizedBox(height: 10),
// Text('Safer: '+"${(_predictions[0]
// ['confidence']*100).toString()}%"),
],
),
),
):Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 300,
width: 250,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.grey,
),
child: Center(child: Text('Image Appears here')),
),
),
SizedBox(height: 10),
// Capture Image from Camera
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 50,
width: double.infinity,
child: RaisedButton(
onPressed: (){
// Methods we created above
loadImageCamera();
},
child: Text('Capture Image'),
color: Color(0xff01AEBC),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
),
),
),
SizedBox(height: 10),
// Capture Image from Gallery
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 50,
width: double.infinity,
child: RaisedButton(
onPressed: (){
// Methods we created above
loadImageGallery();
},
child: Text('Pick Image from Gallery'),
color: Color(0xff01AEBC),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
),
),
),
],
),
),
);
Dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:image_picker/image_picker.dart';
import 'package:tflite/tflite.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State {
bool _loading = true;
File _image;
final imagePicker = ImagePicker();
List _predictions = [];
// For picking image from Gallery
Future loadImageGallery() async {
final image = await imagePicker.getImage(source: ImageSource.gallery);
detectImage(image);
}
// For picking image from Camera
Future loadImageCamera() async {
final image = await imagePicker.getImage(source: ImageSource.camera);
detectImage(image);
}
@override
void initState() {
// TODO: implement initState
super.initState();
loadModel();
}
// LoadModel() for connection app with TensorFlow Lite
loadModel() async{
Tflite.close();
await Tflite.loadModel(model: 'assets/model_unquant.tflite',
labels: 'assets/labels.txt');
}
// Method for Image detection
Future detectImage(image) async {
var prediction = await Tflite.runModelOnImage(
path: image.path,
numResults: 2,
threshold: 0.6,
imageMean: 127.5,
imageStd: 127.5,
);
setState(() {
_loading = false;
if (image != null) {
_image = File(image.path);
_predictions = prediction;
} else {
print('No image selected.');
}
});
// setState(() {
// _loading = false;
// _predictions = prediction;
// });
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
// Appbar displayed here
appBar: AppBar(
title: Text('Mask Detection',
style: GoogleFonts.robotoCondensed(),
),
),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// Image will display here
_loading == false ? Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
child: Column(
children: [
Container(
height: 280,
width: 220,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Image.file(_image)),
),
SizedBox(height: 10),
Text(_predictions[0]['label'].toString().substring(2),
style: GoogleFonts.robotoCondensed(
fontSize: 20,
),
),
SizedBox(height: 10),
// Text('Safer: '+"${(_predictions[0]['confidence']*100).toString()}%"),
],
),
),
):Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 300,
width: 250,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.grey,
),
child: Center(child: Text('Image Appears here')),
),
),
SizedBox(height: 10),
// Button for taking Image from Camera
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 50,
width: double.infinity,
child: RaisedButton(
onPressed: (){
loadImageCamera();
},
child: Text('Capture Image'),
color: Color(0xff01AEBC),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
),
),
),
SizedBox(height: 10),
// Button for taking Image from Gallery
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 50,
width: double.infinity,
child: RaisedButton(
onPressed: (){
loadImageGallery();
},
child: Text('Pick Image from Gallery'),
color: Color(0xff01AEBC),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
),
),
),
],
),
),
);
}
}
第 2 步:现在导航到 main。 dart() 文件并返回 Material App()。
首先,我们在 main函数的runApp 中声明了MyApp() 。然后我们为MyApp创建了StatelessWidget ,其中我们返回了MaterialApp()。在这种MaterialApp(),我们已经给我们的应用程序的标题,然后宣布我们的应用程序的主题,primaryColor为蓝色。然后我们在主页中给出了我们的第一个屏幕或滑块应用程序: HomePage()
Dart
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
// Material App
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
brightness: Brightness.dark,
primaryColor: Color(0xff01AEBC),
),
// Main Screen in our app
home: HomePage(),
);
}
}
第 3 步:现在为 HomePage() 类声明 StatefulWidget()。
在这个StatefulWidget() 中,我们在 state函数下声明了各种变量。之后,我们为loadImageGallery()和loadImageCamera()声明了方法。这些方法用于的帮助下选择从画廊和摄像机的图像 我们导入的image_picker 库。
Dart
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State {
// Variables Declared
bool _loading = true;
File _image;
final imagePicker = ImagePicker();
List _predictions = [];
// Methods to pick the image from Camera and Gallery
Future loadImageGallery() async {
final image = await imagePicker.getImage(source: ImageSource.gallery);
detectImage(image);
}
Future loadImageCamera() async {
final image = await imagePicker.getImage(source: ImageSource.camera);
detectImage(image);
}
第 4 步:现在继续使用 Google Teachable Machine。
现在开始使用Google Teachable Machine 。您可以在哪里训练用于掩码检测的模型。现在单击图像项目。在这里,您必须创建两个类,一个用于遮罩,另一个用于无遮罩。现在在Mask Class单击WebCam以从各个角度记录您的面罩。以同样的方式,您将从所有角度在无面具类中记录您的无面具脸。现在点击训练模型。
完成后,您将单击“导出模型” 。
第1步:
第2步:
第 3 步:
然后点击Tensorflow Lite并在其中选择Floating point然后点击Download my model 。现在下载模型后提取文件。现在将提取的文件添加到pubspec.yaml文件中的资产文件夹。
第 5 步:现在添加以下代码行以将您的模型导入您的应用程序。
现在我们已经创建了loadModel()我们在这个方法中添加了我们下载的文件的提取文件。我们已经在initState()中初始化了loadModel()。之后,我们创建了用于检测图像的detectImage() 。之后,我们设置了更新图像的状态。
我们已经使用dispose()结束了该函数。
Dart
//Initialize the state
@override
void initState() {
// TODO: implement initState
super.initState();
loadModel();
}
// Added extracted files in loadModel() function
loadModel() async{
Tflite.close();
await Tflite.loadModel(model: 'assets/model_unquant.tflite',
labels: 'assets/labels.txt');
}
// Created detectImage() for detecting the image
Future detectImage(image) async {
var prediction = await Tflite.runModelOnImage(
path: image.path,
numResults: 2,
threshold: 0.6,
imageMean: 127.5,
imageStd: 127.5,
);
setState(() {
_loading = false;
if (image != null) {
_image = File(image.path);
_predictions = prediction;
} else {
print('No image selected.');
}
});
}
// Ended the function
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
第 6 步:之后,我们给出了应用程序的 UI。
在这个StateFulWidget() 中,我们已经声明了Scaffold() 。我们在这个应用栏中声明了Appbar() ,我们在Text Widget 中给出了我们的应用程序的标题。在 body 部分的appbar之后,我们已经声明了Column() ,其中图像和按钮将出现在另一个下方。当我们点击捕获图像按钮时,设备的摄像头将打开,您必须捕获将检测掩码的图像。
以同样的方式单击Pick Image from Gallery 。您的文件管理器将打开,您可以从中选择用于检测蒙版的图像。
Dart
@override
Widget build(BuildContext context) {
return Scaffold(
// Appbar declared
appBar: AppBar(
title: Text('Mask Detection',
style: GoogleFonts.robotoCondensed(),
),
),
body: SingleChildScrollView(
// Column containing images and buttons
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// Image will display here
_loading == false ? Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
child: Column(
children: [
Container(
height: 280,
width: 220,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Image.file(_image)),
),
SizedBox(height: 10),
Text(_predictions[0]['label'].toString().substring(2),
style: GoogleFonts.robotoCondensed(
fontSize: 20,
),
),
SizedBox(height: 10),
// Text('Safer: '+"${(_predictions[0]
// ['confidence']*100).toString()}%"),
],
),
),
):Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 300,
width: 250,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.grey,
),
child: Center(child: Text('Image Appears here')),
),
),
SizedBox(height: 10),
// Capture Image from Camera
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 50,
width: double.infinity,
child: RaisedButton(
onPressed: (){
// Methods we created above
loadImageCamera();
},
child: Text('Capture Image'),
color: Color(0xff01AEBC),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
),
),
),
SizedBox(height: 10),
// Capture Image from Gallery
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 50,
width: double.infinity,
child: RaisedButton(
onPressed: (){
// Methods we created above
loadImageGallery();
},
child: Text('Pick Image from Gallery'),
color: Color(0xff01AEBC),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
),
),
),
],
),
),
);
面具检测应用程序的完整代码:
Dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:image_picker/image_picker.dart';
import 'package:tflite/tflite.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State {
bool _loading = true;
File _image;
final imagePicker = ImagePicker();
List _predictions = [];
// For picking image from Gallery
Future loadImageGallery() async {
final image = await imagePicker.getImage(source: ImageSource.gallery);
detectImage(image);
}
// For picking image from Camera
Future loadImageCamera() async {
final image = await imagePicker.getImage(source: ImageSource.camera);
detectImage(image);
}
@override
void initState() {
// TODO: implement initState
super.initState();
loadModel();
}
// LoadModel() for connection app with TensorFlow Lite
loadModel() async{
Tflite.close();
await Tflite.loadModel(model: 'assets/model_unquant.tflite',
labels: 'assets/labels.txt');
}
// Method for Image detection
Future detectImage(image) async {
var prediction = await Tflite.runModelOnImage(
path: image.path,
numResults: 2,
threshold: 0.6,
imageMean: 127.5,
imageStd: 127.5,
);
setState(() {
_loading = false;
if (image != null) {
_image = File(image.path);
_predictions = prediction;
} else {
print('No image selected.');
}
});
// setState(() {
// _loading = false;
// _predictions = prediction;
// });
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
// Appbar displayed here
appBar: AppBar(
title: Text('Mask Detection',
style: GoogleFonts.robotoCondensed(),
),
),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// Image will display here
_loading == false ? Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
child: Column(
children: [
Container(
height: 280,
width: 220,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Image.file(_image)),
),
SizedBox(height: 10),
Text(_predictions[0]['label'].toString().substring(2),
style: GoogleFonts.robotoCondensed(
fontSize: 20,
),
),
SizedBox(height: 10),
// Text('Safer: '+"${(_predictions[0]['confidence']*100).toString()}%"),
],
),
),
):Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 300,
width: 250,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.grey,
),
child: Center(child: Text('Image Appears here')),
),
),
SizedBox(height: 10),
// Button for taking Image from Camera
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 50,
width: double.infinity,
child: RaisedButton(
onPressed: (){
loadImageCamera();
},
child: Text('Capture Image'),
color: Color(0xff01AEBC),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
),
),
),
SizedBox(height: 10),
// Button for taking Image from Gallery
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 50,
width: double.infinity,
child: RaisedButton(
onPressed: (){
loadImageGallery();
},
child: Text('Pick Image from Gallery'),
color: Color(0xff01AEBC),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
),
),
),
],
),
),
);
}
}
输出: