Saving the input image from Face detection as a file? [Flutter + Google ML Kit Face Detection] - flutter

is it possible to save the processed image as a File?
Here is what I'm trying to do, our app have a KYC (Know your customer) and we implemented the
face detection to make the users do several poses. What I want is to save them as an image file and upload it on the database
Example Scenario:
App ask the user to smile > The user smiled > save the image.
Here is what I have right now:
Where the app checks if the user smiled
if (faces.isNotEmpty) {
if (inputImage.inputImageData?.size != null &&
inputImage.inputImageData?.imageRotation != null) {
if (faces[0].smilingProbability! > 0.85) {
await _getImg();
}
}
}
Then I call a Function to stop image stream then take a picture (this works but on some physical device it crashes) but if I dont stop the image stream then called the takePicture() right-away it just crashes all the time.
_getImg() async {
setState(() {
globalBusy = true;
});
await _controller.stopImageStream();
var img = await _controller.takePicture();
VerificationVarHandler.livelinesImgsPaths.add(img.path);
}
As you can see it's not the best way at least for me I think, so maybe I can use the
inputImage from the _processCameraImage() because it has a byte? then I can pass that bytes to a decoder and save it locally when I trigger a function?
Or maybe better yet there is more elegant way of achieving this?

You can check out this gfg article - https://www.geeksforgeeks.org/face-detection-in-flutter-using-firebase-ml-kit/
Learn flutter in easiest way - https://auth.geeksforgeeks.org/user/ms471841/articles

Related

How to set a maximum number of files for imagePicker in flutter

let me explain
How can I set a maximum number of files to pick for filepicker so that I can limit the pick of file
so it does not overload the server.
imagePicker does not allow selecting a specific count. I don't think Java does either without developing your own custom gallery. imagePicker just calls to platform code in any case and if that platform doesn't support I think we're out of luck.
One thing you can do is allow the user to pick as many images as they want (so just regular multi image pick) but then just take however many you need then show a toast that says only count number of photos were used. This feels like a decent trade off.
I have solved this by this block of code
Future galleryImage() async {
if (images.length == 0 || images.length < 4) {
var pics = await ImagePicker().pickMultiImage(imageQuality: 10);
if (pics != null && pics.length < 5) {
photos = pics;
pics.forEach((element) {
images.add(File(element.path));
update();
print('length: ${images.length}');
});
update();
}

How to use StreamBuilder in FirebaseStorage to inform my App from changes in my Firebase Storage? In Flutter

Here is my challenge:
I'm using the following example from https://firebase.flutter.dev/docs/storage/usage/
to upload images to my FireBaseStorage from my phone gallery (which delivers me the String filepath-variable).
Future<void> handleTaskExample2(String filePath) async {
File largeFile = File(filePath);
firebase_storage.UploadTask task = firebase_storage.FirebaseStorage.instance
.ref('uploads/picture-to-upload.jpeg')
.putFile(largeFile);
task.snapshotEvents.listen((firebase_storage.TaskSnapshot snapshot) {
print('Task state: ${snapshot.state}');
print(
'Progress: ${(snapshot.bytesTransferred / snapshot.totalBytes) * 100} %');
}, onError: (e) {
print(task.snapshot);
if (e.code == 'permission-denied') {
print('User does not have permission to upload to this reference.');
}
});
try {
await task;
print('Upload complete.');
} on firebase_core.FirebaseException catch (e) {
if (e.code == 'permission-denied') {
print('User does not have permission to upload to this reference.');
}
// ...
}
}
Actually, everything works fine. My uploaded Image to my Storage gets shown in my GridView inside the App...
But if I upload an Image to my Storage manually over the FireBase Website, my gridView (where the pictures from my storage are shown) is not auto-updating.
But if I change my screen and come back, the manually uploaded picture is shown.
It looks like I need something like a StreamBuilder that my App gets informed whenever changes happen in my Storage.
Does anyone have an Idea how to implement this or any other ideas to solve my problem?
Thanks
The listAll and list only get the data once so you unfortunately can't have a stream on them. You have 2 options here.
Call the listAll in a periodic interval like every 2-3 min
Create a cloud functions that get's triggered when files get uploaded to that specific directory and change a value in RTDB or Firestore. In the App you can listen to that data. Idealy it should be just a timestamp. You can store in your app the last timestamp you got from the database and if that changes just call listAll.
It depends on your usecase what would fit for you the best.

Flutter Blue Sending Quite Large File from BLE device to App

I need to send a file .txt from a device to my app (worst case almost 2mb). The BLE device divide the file into packages. I don't know if my method is correct, but I create a loop of characteristic.write/characteristic.read telling everytime what package the device has to send.
Here's my code:
for(int i = 0; i < packNumber.length; i++) {
initialValue = '9,50,100,$i,0,$checksumId,0/';
await characteristic
.write(utf8.encode(initialValue)).then((wValue) async {
await Future.delayed(Duration(milliseconds: 100)).then((value) async {
await characteristic.read().then((rValue) {
//do something with rVlaue
});
});
});
}
It works, but is it the best solution? And in case how can I speed up the transfer (for now I have to set a delay before reading, waiting for characteristic.write to finish)?
Thank you guys
You should change the remote device to send notifications instead of using reads. That gives maximum throughput.

Flutter: Get information from scanned barcode number

I am quite new to Flutter, and I am currently working on an application that needs barcode reading. So I used the barcode_scan library, and I am now able to get the barcode number from a scanned barcode.
To be clear, I am not asking how to scan a barcode / get the barcode number.
My question is: how can I get more information about a product from its barcode number in Flutter (e.g. product name)? Can I do this from the barcode_scan library, or will I need something else?
Edit: Forgot to mention, when scanning QR codes I am able to get the information it encodes (e.g. product name or URL), but this is not the case with barcodes.
My current (relevant) code is as follows:
String result = 'Hey there!';
Future scanBarcode() async {
if(await Permissions.checkCameraPermission()) {
try {
await BarcodeScanner.scan().then((scan_result) {
//here scan_result is the obtained barcode number
setState(() { result = scan_result; });
});
}
//handling exceptions...
}
else {
setState(() { result = 'Camera permission denied'; });
}
}
(Side note, here Permissions.checkCameraPermission() is a function I created to check if camera permission is granted, shouldn't be relevant for the question).
I'm using the same plugin for scanning barcode or qr code for my flutter app..
String result = 'Hey there!';
Future scanBarcode() async {
if(await Permissions.checkCameraPermission()) {
try {
// I get the scan result from BarcodeScanner this way and it is working for me.
result = await BarcodeScanner.scan();
}
//handling exceptions...
}
else {
setState(() { result = 'Camera permission denied'; });
}
}
Well, it seems the only plausible way to do it from Flutter would be to use a barcode lookup API like #RichardHeap proposed in the comments. If my app was Flutter only (without a backend server connected to it) I believe I would have gone that way.
But I guess I'll just send the barcode number itself to the backend and deal with it on the server-side.
What I understand is, on scanning the code, you need the information / data about the product.
If I understood it right, there are several aggregators of the barcode. You can get APIs from them. But there is not single place from where you get all the information.

Xamarin.Forms Taking picture with Plugin.Media not working

I'm using the Plugin.Media from #JamesMontemagno version 2.4.0-beta (which fixes picture orientation), it's working on Adroind 4.1.2 (Jelly Bean) and Marshmallow, but NOT on my Galaxy S5 Neo with Android version 5.1.1.
Basically when I take a picture it never returns back on the page from where I started the process; always returns back to the initial home page.
On devices where it works, when I take a picture, I see that first of all the application fires OnSleep, then after taking the picture fires OnResume.
On my device where is NOT working it fires OnSleep and after taking the picture doesn't fire OnResume, it fires the initialization page and then OnStart.
For this reason it doesn't open the page where I was when taking the picture.
What should I do to make sure it fires OnResume returning to the correct page and not OnStart which returns on initial fome page ?
In addition, when I take a picture it takes almost 30 seconds to get back to the code after awaiting TakePhotoAsync process, and it's too slow!
Following my code:
MyTapGestureRecognizerEditPicture.Tapped += async (sender, e) =>
{
//Display action sheet
String MyActionResult = await DisplayActionSheet(AppLocalization.UserInterface.EditImage,
AppLocalization.UserInterface.Cancel,
AppLocalization.UserInterface.Delete,
AppLocalization.UserInterface.TakePhoto,
AppLocalization.UserInterface.PickPhoto);
//Execute action result
if (MyActionResult == AppLocalization.UserInterface.TakePhoto)
{
//-----------------------------------------------------------------------------------------------------------------------------------------------
//Take photo
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert(AppLocalization.UserInterface.Alert, AppLocalization.UserInterface.NoCameraAvailable, AppLocalization.UserInterface.Ok);
}
else
{
var MyPhotoFile = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory = "MyApp",
Name = "MyAppProfile.jpg",
SaveToAlbum = true,
PhotoSize = Plugin.Media.Abstractions.PhotoSize.Small
});
if (MyPhotoFile != null)
{
//Render image
MyProfilePicture.Source = ImageSource.FromFile(MyPhotoFile.Path);
//Save image on database
MemoryStream MyMemoryStream = new MemoryStream();
MyPhotoFile.GetStream().CopyTo(MyMemoryStream);
byte[] MyArrBytePicture = MyMemoryStream.ToArray();
await SaveProfilePicture(MyArrBytePicture);
MyPhotoFile.Dispose();
MyMemoryStream.Dispose();
}
}
}
if (MyActionResult == AppLocalization.UserInterface.PickPhoto)
{
//-----------------------------------------------------------------------------------------------------------------------------------------------
//Pick photo
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsPickPhotoSupported)
{
await DisplayAlert(AppLocalization.UserInterface.Alert, AppLocalization.UserInterface.PermissionNotGranted, AppLocalization.UserInterface.Ok);
}
else
{
var MyPhotoFile = await CrossMedia.Current.PickPhotoAsync();
if (MyPhotoFile != null)
{
//Render image
MyProfilePicture.Source = ImageSource.FromFile(MyPhotoFile.Path);
//Save image on database
MemoryStream MyMemoryStream = new MemoryStream();
MyPhotoFile.GetStream().CopyTo(MyMemoryStream);
byte[] MyArrBytePicture = MyMemoryStream.ToArray();
await SaveProfilePicture(MyArrBytePicture);
MyPhotoFile.Dispose();
MyMemoryStream.Dispose();
}
}
}
};
Please help!! We need to deploy this app but we cannot do it with this problem.
Thank you in advance!
It is perfectly normal to have the Android OS terminate and restart an Activity. As you are seeing, your app's Activity it will be automatically restarted when the camera app exits and the OS returns control to your app. The odds are it just needed more memory in order to take that photo with the Neo's 16MP camera, you can watch the logcat output to confirm that.
Restarted – It is possible for an activity that is anywhere from paused to stopped in the lifecycle to be removed from memory by Android. If the user navigates back to the activity it must be restarted, restored to its previously saved state, and then displayed to the user.
What to do:
So on the Xamarin.Forms OnStart lifecycle method you need to restore your application to a valid running state (initializing variables, preforming any bindings, etc...).
Plug code:
The Android platform code for the TakePhotoAsync method looks fine to me, but remember that the memory for that image that is passed back via the Task will be doubled as it is marshaled from the ART VM back the Mono VM. Calling GC.Collect() as soon as possible after the return will help (but your Activity is restarting anyway...)
public async Task<MediaFile> TakePhotoAsync(StoreCameraMediaOptions options)
{
~~~
var media = await TakeMediaAsync("image/*", MediaStore.ActionImageCapture, options);
In turn calls:
this.context.StartActivity(CreateMediaIntent(id, type, action, options));
Not much less you can really do within the Android OS to popup the Camera.
In addition, when I take a picture it takes almost 30 seconds to get back to the code after awaiting TakePhotoAsync process, and it's too slow!
Is that on your Neo? Or all devices?
I would call that very suspect (ie. a bug) as even flushing all the Java memory after the native Camera Intent/Activity and the restart time for your app's Activity should not take 30 seconds on a oct-core 1.6 GHz Cortex... but I do not have your device, app and code in front of me....