259 lines
7.8 KiB
Dart
259 lines
7.8 KiB
Dart
import 'dart:io';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_tflite/flutter_tflite.dart';
|
|
import 'package:image_picker/image_picker.dart';
|
|
import 'package:tfltiemy/splashscreen.dart';
|
|
import 'dart:developer' as devtools;
|
|
|
|
void main() {
|
|
runApp(const MyApp());
|
|
}
|
|
|
|
class MyApp extends StatelessWidget {
|
|
const MyApp({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MaterialApp(
|
|
title: 'Frescitrico',
|
|
theme: ThemeData(
|
|
colorScheme: ColorScheme.fromSeed(seedColor: Colors.orange),
|
|
useMaterial3: true,
|
|
),
|
|
debugShowCheckedModeBanner: false,
|
|
home: SplashScreen(),
|
|
);
|
|
}
|
|
}
|
|
|
|
class MyHomePage extends StatefulWidget {
|
|
const MyHomePage({super.key});
|
|
|
|
@override
|
|
State<MyHomePage> createState() => _MyHomePageState();
|
|
}
|
|
|
|
class _MyHomePageState extends State<MyHomePage> {
|
|
File? filePath;
|
|
String label = 'Hasil Klasifikasi';
|
|
double confidence = 0.0;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadModel();
|
|
}
|
|
|
|
Future<void> _loadModel() async {
|
|
try {
|
|
String? res = await Tflite.loadModel(
|
|
model: "assets/modeljeruk.tflite",
|
|
labels: "assets/labels.txt",
|
|
numThreads: 1,
|
|
isAsset: true,
|
|
useGpuDelegate: false,
|
|
);
|
|
devtools.log("Model loaded: $res");
|
|
} catch (e) {
|
|
devtools.log("Error loading model: $e");
|
|
}
|
|
}
|
|
|
|
Future<void> _runModel(File imageFile) async {
|
|
try {
|
|
var recognitions = await Tflite.runModelOnImage(
|
|
path: imageFile.path,
|
|
imageMean: 0.0,
|
|
imageStd: 255.0,
|
|
numResults: 2,
|
|
threshold: 0.2,
|
|
asynch: true,
|
|
);
|
|
|
|
if (recognitions != null && recognitions.isNotEmpty) {
|
|
setState(() {
|
|
confidence = (recognitions[0]['confidence'] as double) * 100;
|
|
label = recognitions[0]['label'] as String;
|
|
});
|
|
} else {
|
|
devtools.log("No recognitions found.");
|
|
}
|
|
} catch (e) {
|
|
devtools.log("Error running model: $e");
|
|
}
|
|
}
|
|
|
|
Future<void> _pickImage(ImageSource source) async {
|
|
try {
|
|
final picker = ImagePicker();
|
|
final XFile? image = await picker.pickImage(source: source);
|
|
|
|
if (image == null) return;
|
|
|
|
final imageFile = File(image.path);
|
|
|
|
setState(() {
|
|
filePath = imageFile;
|
|
label = "Processing...";
|
|
confidence = 0.0;
|
|
});
|
|
|
|
await _runModel(imageFile);
|
|
} catch (e) {
|
|
devtools.log("Error picking image: $e");
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
Tflite.close();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
backgroundColor: Colors.orange,
|
|
title: Padding(
|
|
padding: const EdgeInsets.only(
|
|
left: 5,
|
|
), // Memberikan jarak 20 dari kiri
|
|
child: const Text(
|
|
"Frescitrico",
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.w800,
|
|
fontSize: 25, // Menambahkan fontWeight
|
|
),
|
|
),
|
|
),
|
|
centerTitle: false, // Pastikan ini false untuk membuat judul rata kiri
|
|
),
|
|
|
|
body: SingleChildScrollView(
|
|
child: Column(
|
|
children: [
|
|
const SizedBox(height: 20),
|
|
// Area Hasil Gambar
|
|
Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 20),
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
color: Colors.orange.shade100,
|
|
borderRadius: BorderRadius.circular(10),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.orange.withOpacity(0.3),
|
|
blurRadius: 0,
|
|
offset: const Offset(0, 0),
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
children: [
|
|
Container(
|
|
height: 290,
|
|
width: 290,
|
|
decoration: BoxDecoration(
|
|
image:
|
|
filePath == null
|
|
? const DecorationImage(
|
|
image: AssetImage('assets/uploadilu.png'),
|
|
fit: BoxFit.contain,
|
|
)
|
|
: null,
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
child:
|
|
filePath == null
|
|
? const SizedBox()
|
|
: Image.file(filePath!, fit: BoxFit.contain),
|
|
),
|
|
const SizedBox(height: 20),
|
|
Text(
|
|
label,
|
|
style: const TextStyle(
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
// const SizedBox(height: 5),
|
|
// Text(
|
|
// confidence > 0
|
|
// ? "Confidence: ${confidence.toStringAsFixed(2)}%"
|
|
// : "Ambil gambar untuk memulai",
|
|
// style: const TextStyle(fontSize: 16),
|
|
// ),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 20),
|
|
const Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 20),
|
|
child: Text(
|
|
"Ambil gambar buah jeruk dengan kamera atau pilih dari galeri, dan temukan hasilnya segera!!!",
|
|
textAlign: TextAlign.justify,
|
|
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
|
),
|
|
),
|
|
const SizedBox(height: 20),
|
|
// Tombol Kamera
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
|
child: ElevatedButton.icon(
|
|
onPressed: () => _pickImage(ImageSource.camera),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.orange,
|
|
// padding: const EdgeInsets.symmetric(
|
|
// horizontal: 0,
|
|
// vertical: 20,
|
|
// ),
|
|
minimumSize: Size.fromHeight(60),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
),
|
|
icon: const Icon(
|
|
Icons.camera_alt,
|
|
size: 26,
|
|
color: Color.fromARGB(255, 255, 255, 255),
|
|
),
|
|
label: const Text(
|
|
"Buka Kamera",
|
|
style: TextStyle(color: Colors.white, fontSize: 17),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 10),
|
|
// Tombol Galeri
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
|
child: ElevatedButton.icon(
|
|
onPressed: () => _pickImage(ImageSource.gallery),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.orange,
|
|
// padding: const EdgeInsets.symmetric(
|
|
// horizontal: 104,
|
|
// vertical: 20,
|
|
// ),
|
|
minimumSize: Size.fromHeight(60),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
),
|
|
icon: const Icon(Icons.image, size: 26, color: Colors.white),
|
|
label: const Text(
|
|
"Unggah Dari File",
|
|
style: TextStyle(color: Colors.white, fontSize: 17),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|