I am coding a plant species recognition app. App takes image from gallery and predict the plant species. So i should pick image from gallery and show the accuracy score.
I did everything exactly the same from the flutter machine learning book but app doesnt show the picked image and accuracy score. I pick image from gallery but it still says "no image selected".
If i delete these lines, i can pick the image from gallery and show on the screen. But then i cant apply AI operations.
await analyzeTFLite();
await recognizeImage(File(image.path));
Screen should be as first pic. But mine is as second pic. The whole code is below. Thanks for your help.
import 'dart:io';
import 'package:tflite/tflite.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class PlantSpeciesRecognition extends StatefulWidget {
var model;
PlantSpeciesRecognition(this.model);
#override
_PlantSpeciesRecognitionState createState() =>
_PlantSpeciesRecognitionState();
}
class _PlantSpeciesRecognitionState extends State<PlantSpeciesRecognition> {
File _image;
bool _busy = false;
List _recognitions;
Future chooseImageGallery() async {
debugPrint("choose image function");
var image = await ImagePicker().getImage(source: ImageSource.gallery);
//var image = await ImagePicker.pickImage(source: ImageSource.gallery);
if (image == null) {
debugPrint("choose image if");
return;
}
setState(() {
_busy = true;
});
await analyzeTFLite();
await recognizeImage(File(image.path));
setState(() {
debugPrint("choose image set state");
_busy = false;
//_image = image as File;
_image = File(image.path);
});
}
Future analyzeTFLite() async {
Tflite.close();
String res = await Tflite.loadModel(
model: "assets/model.tflite",
labels: "assets/labels.txt"
);
print('Model Loaded: $res');}
Future recognizeImage(File image) async{
var recognitions = await Tflite.runModelOnImage(path: _image.path);
setState(() {
_recognitions = recognitions;
});
print("Recognition Result: $_recognitions");
}
#override
Widget build(BuildContext context) {
List<Widget> stackChildren = [];
Size size = MediaQuery.of(context).size;
stackChildren.clear();
stackChildren.add(Positioned(
top: 0.0,
left: 0.0,
width: size.width,
child: _image == null
? Center(child: Text("No Image Selected"))
: Image.file(_image),
));
stackChildren.add(Center(
child: Column(
children: _recognitions != null
? _recognitions.map((res) {
return Text(
"${res["label"]}: ${res["confidence"].toStringAsFixed(3)}",
style: TextStyle(
color: Colors.black,
fontSize: 20.0,
background: Paint()
..color = Colors.white,
),
);
}).toList() : [],
),
));
return Scaffold(
appBar: AppBar(
title: const Text('Plant Species Recognition'),
),
floatingActionButton: FloatingActionButton(
onPressed: chooseImageGallery,
tooltip: 'Pick Image',
child: Icon(Icons.image),
),
body: Stack(
children: stackChildren,
),
);
}
}
Related
I am using ImagePicker in a flutter app, but we should specify the source of the Image.
How can I let the choice to the user?
File? selectedImage;
getImage() async {
XFile? file = await ImagePicker().pickImage(source: ImageSource.camera);
selectedImage = File(file!.path);
setState(() {});
}
You can show a dialog for to choose option.
getImage() async {
bool? isCamera = await showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
ElevatedButton(
onPressed: () {
Navigator.of(context).pop(true);
},
child: Text("Camera"),
),
SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop(false);
},
child: Text("gallery "),
),
],
),
),
);
if (isCamera == null) return;
XFile? file = await ImagePicker()
.pickImage(source: isCamera ? ImageSource.camera : ImageSource.gallery);
selectedImage = File(file!.path);
setState(() {});
}
You need to make two Text one for gallery and one for Camera and on thier onTap() you should pass a function which will be like
void imageGalleryBottomSheet(
{BuildContext context,
VoidCallback onCameraTap,
VoidCallback onGalleryTap}) {
//your code logic
}
The sdk that I use is as follows.
sdk: ">=2.7.0 <3.0.0"
image_picker: ^0.6.7
image_picker_for_web: ^0.1.0
firebase_storage: ^3.1.6
cloud_firestore: ^0.13.7
When uploading an image to storage, I try to reduce the size of the image file.
And this is the code for image upload.
import 'package:image_picker/image_picker.dart';
import 'package:firebase/firebase.dart' as fb;
import 'package:omd_test/widget/custom_loading.dart';
class TestScreen extends StatefulWidget {
#override
State<TestScreen> createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
PickedFile _image;
String imageUrl;
#override
Widget build(BuildContext context) {
return SafeArea(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Scaffold(
appBar: AppBar(
title: Text("TEST"),
),
body: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
children: [
Container(
width: 200,
height: 200,
child: _image == null
? Container()
: Image.network(
_image.path,
)),
TextButton(
onPressed: () {
_getImagesPicker();
},
child: Text(
"Pick",
style: TextStyle(color: Colors.black),
)),
SizedBox(
height: 20,
),
TextButton(
onPressed: () async {
if (_image != null) {
await imageUpload(_image);
setState(() {
_image = null;
});
} else
print("No Image");
},
child: Text(
"Upload"
)),
],
),
),
),
),
);
}
Future<void> _getImagesPicker() async {
try {
final _imagePath = await ImagePicker().getImage(
source: ImageSource.gallery,
imageQuality: 10,
maxHeight: 50,
maxWidth: 50
);
setState(() {
_image = _imagePath;
});
} catch (err) {
print(err);
}
}
Future<String> imageUpload(PickedFile image) async {
var bytes = await image.readAsBytes();
fb.StorageReference _storage =
fb.storage().ref('testScreen/${image.path}.jpg');
fb.UploadTaskSnapshot uploadTaskSnapshot = await _storage
.put(bytes, fb.UploadMetadata(contentType: 'image/png'))
.future;
var imageUri = await uploadTaskSnapshot.ref.getDownloadURL();
imageUrl = imageUri.toString();
return imageUrl;
}
}
I tested by changing the value of 'imageQuality' of ImagePicker, but when uploaded to storage, all image files were the same size.
enter image description here
Can I know what the problem is?
Is it a problem to upload to storage?
Thank you.
From the image_picker repository, there's some inconsistency in what adjustments can be made to what type of images.
Here's an overview that might give some important lead.
Can I know what the problem is?
The comments in the actual implementation of the package has some lines[here]:
//Note that the `maxWidth`, `maxHeight` and `imageQuality` arguments are not supported on the web. If any of these arguments is supplied, it'll be silently ignored by the web version of the plugin.
However, there's still an implementation of the resizing of a selected image though.
Is it a problem to upload to storage?
Seemingly no.
Here's what you may wish to try going forward; run your app on other platforms and try to establish if the image is resized, this will help you single out if it's only on the web that the quality is not being adjusted.
If you establish this to be so, you may wish to have your own implementation of quality/size adjustment of the picked media, you can utilise kIsWeb boolean property to determine if it's web, then apply your own implementation.
if(kIsWeb){
//Adjust quality/size
}else{
//use the already adjusted media
}
Note this comment as well:
//Compression is only supported for certain image types such as JPEG and on Android PNG and WebP, too. If compression is not supported for the image that is picked, a warning message will be logged.
I am coding an application for recognizing plant species. I want to pick an image and show that on screen but i can't. Image returns null. Although i choose photo from gallery, it still says "no image selected".
I also added read_external_storage permission to android manifests.
import 'dart:io';
import 'package:tflite/tflite.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class PlantSpeciesRecognition extends StatefulWidget {
var model;
PlantSpeciesRecognition(this.model);
#override
_PlantSpeciesRecognitionState createState() =>
_PlantSpeciesRecognitionState();
}
class _PlantSpeciesRecognitionState extends State<PlantSpeciesRecognition> {
File _image;
bool _busy = false;
List _recognitions;
Future chooseImageGallery() async {
debugPrint("choose image function");
var image = await ImagePicker().getImage(source: ImageSource.gallery);
//var image = await ImagePicker.pickImage(source: ImageSource.gallery);
if (image == null) {
debugPrint("choose image if");
return;
}
//await analyzeTFLite();
setState(() {
debugPrint("choose image set state");
_busy = true;
_image = image as File;
});
}
#override
Widget build(BuildContext context) {
List<Widget> stackChildren = [];
Size size = MediaQuery.of(context).size;
//stackChildren.clear();
stackChildren.add(Positioned(
top: 0.0,
left: 0.0,
width: size.width,
child: _image == null ? Text("No Image Selected") : Image.file(_image),
));
return Scaffold(
appBar: AppBar(
title: const Text('Plant Species Recognition'),
),
floatingActionButton: FloatingActionButton(
onPressed: chooseImageGallery,
tooltip: 'Pick Image',
child: Icon(Icons.image),
),
body: Stack(
children: stackChildren,
),
);
}
}
this is normal because it is not the file that is returned. Correct the following line:
setState(() {
debugPrint("choose image set state");
_busy = true;
_image = File(image.path); //change this line.
});
I have a problem and I cannot solve it and I did not find a source to solve it on Google, I have a page where I view a PDF file through a link, and I have a CircularProgressIndicator and I want to replace it with a progress bar showing the percentage of downloading the file, can I do that?
I have attached my code
import 'package:flutter/material.dart';
import 'package:flutter_plugin_pdf_viewer/flutter_plugin_pdf_viewer.dart';
class ReadPdf extends StatefulWidget {
final String value;
ReadPdf({Key key, this.value}) : super(key: key);
#override
_ReadPdfState createState() => _ReadPdfState();
}
class _ReadPdfState extends State<ReadPdf>{
bool _isloading = false, _isInit = true;
PDFDocument document;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Color.fromRGBO(58, 66, 86, 1.0),
body: Container(
child: Column(
children: <Widget>[
Expanded(child:Center(
child: _isInit? MaterialButton(child: Text('Go'), onPressed: () {_loadFromURL(widget.value);},
color: Color.fromRGBO(64, 75, 96, .9),
textColor: Colors.white,
) : _isloading? Center(child: CircularProgressIndicator(),) : PDFViewer(document: document,indicatorBackground: Colors.deepPurple,),
),),
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
],
),
],
),
),
),
);
}
_loadFromURL(String url) async{
setState(() {
_isInit = false;
_isloading = true;
});
document = await PDFDocument.fromURL('${url}'); setState(() {
_isloading = false;
});
}
}
I have an app with the same feature, I used Dio this package supports downloading a file to your phone.
All you need to do is
Dio dio = Dio();
dio.download("*YOUR URL WHERE YOU WANT TO DOWNLOAD A FILE*",
"*YOUR DESTINATION PATH*", onReceiveProgress: (rec, total) {
print("Downloading " + ((rec / total) * 100).toStringAsFixed(0) + "%");
});
Never used this for pdf, but I've tried it for NetworkImage().
Not sure if it'll help. But you can just try it if there's a way to use loadingBuilder in your code.
Image.network(
imageUrl,
fit: BoxFit.cover,
loadingBuilder: (BuildContext context, Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null)
return child;
else {
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes
: null,
),
);
}
},
);
u can use flutter_cached_pdfview
and this an example to view a pdf from URL and cache it with placeholder
u can replace placeholder with any widget like CircularProgressIndicator
PDF().cachedFromUrl(
'http://africau.edu/images/default/sample.pdf',
placeholder: (progress) => Center(child: Text('$progress %'))
)
take a look https://pub.dev/packages/flutter_cached_pdfview
i need to save file eg.jpg to "internalstorage/appname/files/"
and show a notification if it does exists already in folder. when a button is pressed/activity intiated,it should download file to local storage of andorid device with dart code.
help me find solution.
**code:**
import 'dart:io';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import './landing_page.dart';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
import 'package:simple_permissions/simple_permissions.dart';
import 'package:flutter/services.dart';
class MoviesPage extends StatefulWidget {
#override
State createState() => new MoviesPageState();
}
class MoviesPageState extends State<MoviesPage> {
final dUrl ="https://cdn.putlockers.es/download/0BBCA7584749D4E741747E32E6EB588AEA03E40F";
bool downloading = false;
var progressString = "";
static const MethodChannel _channel =
const MethodChannel('flutter_downloader');
#override
void initState() {
super.initState();
downloadFile();
}
Future<void> downloadFile() async {
Dio dio = Dio();
try {
var dir = await getApplicationDocumentsDirectory();
await dio.download(dUrl, "${dir.path}/file.torrent",
onProgress: (rec, total) {
print("Rec: $rec , Total: $total");
setState(() {
downloading = true;
progressString = ((rec / total) * 100).toStringAsFixed(0) + "%";
});
});
} catch (e) {
print(e);
}
setState(() {
downloading = false;
progressString = "Completed";
});
print("Download completed");
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("AppBar"),
),
body: Center(
child: downloading
? Container(
height: 120.0,
width: 200.0,
child: Card(
color: Colors.black,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(),
SizedBox(
height: 20.0,
),
Text(
"Downloading File: $progressString",
style: TextStyle(
color: Colors.white,
),
)
],
),
),
)
: Text("No Data"),
),
);
}
}
thanks in advance.post your solutions in full fludged manner.
I've checked the minimal repro you've posted and it seems that you're using Flutter plugin dio to download the file. I've reused the Future<void> downloadFile() from your code and modified it a bit to check if the plugin works as expected. As of version 3.0.10 of the dio plugin, the onProgress on dio.download() is now onReceiveProgress, but it still essentially has the same function.
Here's the method for downloading the image file based from your code with a bit of modification.
Future downloadFile() async {
Dio dio = Dio();
var dir = await getApplicationDocumentsDirectory();
var imageDownloadPath = '${dir.path}/image.jpg';
await dio.download(imageSrc, imageDownloadPath,
onReceiveProgress: (received, total) {
var progress = (received / total) * 100;
debugPrint('Rec: $received , Total: $total, $progress%');
setState(() {
downloadProgress = received.toDouble() / total.toDouble();
});
});
// downloadFile function returns path where image has been downloaded
return imageDownloadPath;
}
The plugin works as expected and successfully downloads the image file. Though I'm unable to verify how you're able to determine that the image that you're trying to download fails on your repro. In my sample app, Future downloadFile() returns a String where the image path is stored. I then use this to update the Image Widget to display the downloaded image - this determines that the download has been successful.
Here's the complete sample app.
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final imageSrc = 'https://picsum.photos/250?image=9';
var downloadPath = '';
var downloadProgress = 0.0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(flex: 5, child: Image.network(imageSrc)),
Expanded(
flex: 2,
child: Row(
children: [
ElevatedButton(
// Download displayed image from imageSrc
onPressed: () {
downloadFile().catchError((onError) {
debugPrint('Error downloading: $onError');
}).then((imagePath) {
debugPrint('Download successful, path: $imagePath');
displayDownloadImage(imagePath);
});
},
child: Text('Download'),
),
ElevatedButton(
// Delete downloaded image
onPressed: () {
deleteFile().catchError((onError) {
debugPrint('Error deleting: $onError');
}).then((value) {
debugPrint('Delete successful');
});
},
child: Text('Clear'),
)
],
),
),
LinearProgressIndicator(
value: downloadProgress,
),
Expanded(
flex: 5,
child: downloadPath == ''
// Display a different image while downloadPath is empty
// downloadPath will contain an image file path on successful image download
? Icon(Icons.image)
: Image.file(File(downloadPath))),
],
),
),
);
}
displayDownloadImage(String path) {
setState(() {
downloadPath = path;
});
}
Future deleteFile() async {
final dir = await getApplicationDocumentsDirectory();
var file = File('${dir.path}/image.jpg');
await file.delete();
setState(() {
// Clear downloadPath on file deletion
downloadPath = '';
});
}
Future downloadFile() async {
Dio dio = Dio();
var dir = await getApplicationDocumentsDirectory();
var imageDownloadPath = '${dir.path}/image.jpg';
await dio.download(imageSrc, imageDownloadPath,
onReceiveProgress: (received, total) {
var progress = (received / total) * 100;
debugPrint('Rec: $received , Total: $total, $progress%');
setState(() {
downloadProgress = received.toDouble() / total.toDouble();
});
});
// downloadFile function returns path where image has been downloaded
return imageDownloadPath;
}
}
In the sample app, clicking the 'Download' button will have the network image displayed at the top portion of the screen downloaded. After the download is successful, the downloaded image will be displayed using Image.file() at the lower portion of the screen.