Video file to image stream in flutter - image

I have a video file in my assets folder (like mp4). I want to read that video file as an image stream, like an image stream in the camera package https://pub.dev/documentation/camera/latest/camera/CameraController/startImageStream.html
I want to pass the image to Tflite model.
Something like that:
controller = loadVideo('assets/example.mp4'); // how to do that?!
controller.startImageStream((CameraImage img) {
Tflite.runPoseNetOnFrame(
bytesList: img.planes.map((plane) {
return plane.bytes;
}).toList(),
imageHeight: img.height,
imageWidth: img.width,
numResults: 1,
threshold: 0.1,
).then((recognitions) {
// ...
}
}
I tried to search in the image_picker and video_player packages, but did not find anything.

What I did is to split the images and save them as files and then send it to the tf model. It's not fast (because you make file and then read it) but it is working, tested on android and it should work on IOS :)
I made a PR in the package flutter_export_video_frame, now it have a function in the name of exportImagesFromFile. It is Returning a Stream of images from video file as Stream<File>.
To get the video file from the asset folder I use the following function:
import 'dart:async';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:path/path.dart';
Future<File> getImageFileFromAssets(String path) async {
final byteData = await rootBundle.load('assets/$path');
final fileName = basename(path);
final file = new File('${(await getTemporaryDirectory()).path}/$fileName');
await file.writeAsBytes(byteData.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
return file;
}
And then to move it to the posenet/model, there is a function that gets File as input:
var results = await Tflite.runPoseNetOnImage(
path: path,
numResults: 1,
);
One possible improvement to this method is to make it works only on the RAM (after you read the video, of course)

Yes, sure you can do that in one of the following ways:
Use the export_video_frame plugin
Use video_thumbnail plugin
You can specify an exact frame by the time parameter.

Related

How to Transform a Blob to An Image in flutter

i want to display an image stored in mysql database
the problem is that i can't convert the blob format into a Uint8list ; i searched and found soulitions but none of them works
Grab the blob from JSON:
var blob = yourJSONMapHere['yourJSONKeyHere'];
var image = BASE64.decode(blob); // image is a Uint8List
Now, use image in a Image.memory
new Container( child: new Image.memory(image));
this soulition didn't work because base64.decode need a string source not a blob file to convert
Don't know if it is relatable to this particular case but had similar issue with Cloud Firestore.
Created blob for storing in this way:
Blob myBlob = Blob(await audioFile.readAsBytes());
saved to Firestore in one field as usual
Then tried to read it back and couldn't figure it out how to get Uint8List from blob I get back from Firestore.
my solution:
//extract blob from field of Firestore document
Blob audioBlob = audioDocFromDb.get("fieldName");
//use .bytes on blob from this source
//package:cloud_firestore_platform_interface/src/blob.dart
Uint8List audioBytes = audioBlob.bytes;
this worked for me.
In my case I was packing up recorded audio and trying to play it back.
I had this problem too, i know the solution now, after many attempts:
Dont forget to upvote!
Uint8List image = Uint8List.fromList(blob.toBytes());
Image.memory(image);
This function has always saved me for getting bytes from a file that is uploaded to a URL.
import 'package:http/http.dart' as http;
// urlImageBlob is the URL where our file is hosted.
Uint8List fileBytes = await http.readBytes(Uri.parse(urlImageBlob));
// Display if are image.
Image.memory(fileBytes);

How to save images from assets to the internal storage in flutter?

I am trying to save the image from assets to internal storage. But, I could not load the image from assets to file. Here is what I have done:
onTap: () async {
final String documentPath = (await getApplicationDocumentsDirectory()).path;
String imgPath = (galleryItems[currentIndex].assetName).substring(7);
File image = await getImageFileFromAssets(imgPath);
print(image.path);
}
I used substring(7) to eliminate assets/ as, my assetName comes as assets/images/foo.jpg.
Future<File> getImageFileFromAssets(String path) async {
final byteData = await rootBundle.load('assets/$path');
final file =
await File('${(await getApplicationDocumentsDirectory()).path}/$path')
.create(recursive: true);
await file.writeAsBytes(byteData.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
return file;
}
After I get image, I don't know how to proceed forward to create a directory with my name in internal storage. And, copy file there.
*Note:- I have editted the post, as some basic mistakes were pointed out.
Update
Here is what I came up with. And it saves image in the /storage/emulated/0/Android/data/com.example.my_project/files/Pics/foo.jpg path.
File image = await getImageFileFromAssets(imgPath);
final extDir = await getExternalStorageDirectory();
// Path of file
final myImagePath = '${extDir.path}/Pics';
// Create directory inside where file will be saved
await new Directory(myImagePath).create();
// File copied to ext directory.
File newImage =
await image.copy("$myImagePath/${basename(imgPath)}");
print(newImage.path);
Here are some links that really helped me:
Flutter How to save Image file to new folder in gallery?
How to Save Image File in Flutter ? File selected using Image_picker plugin
How to convert asset image to File?
Special thanks to #David for the help. Please see comments to understand full scene if you are here to solve your similar problem.
So, I am accepting the answer from #David.
You are trying to create a file object in a path that doesn't exist. You're using your asset path, the path relative to the root of your Flutter project. However, this path doesn't exist in the device's documents folder, so the file can't be created there. The file also doesn't exist in the assets folder because you're prepending the documents path.
To fix your issue, you should pass assetName to rootBundle.load(), without the documents path and open the File() somewhere like $documentPath/foo.jpg
Edit:
To create the file you still have to call File.create, so you need to run:
final file = await File('$documentPath/images/foo.jpg').create(recursive: true);
For future reference, this is just to update the solution of #Biplove which really helped me a lot as a newbie...
Future<File> getImageFileFromAssets(String unique, String filename) async {
ByteData byteData = await rootBundle.load(assets/filename));
// this creates the file image
File file = await File('$imagesAppDirectory/$filename').create(recursive: true);
// copies data byte by byte
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
return file;
}
Thanks.

how to convert image to byte and again convert it to image in flutter?

I am trying to use the image_picker plugin. I can get the image as file using this plugin. I need to convert this image to bytes and send to a api. So I tried to use dart:convert to convert the image to byte string. Now when I decode I am getting a Uint8List type. How to convert this to a file and display in a Image.file(). I couldn’t proceed from here. Can someone help me with this.
consider i am getting this decodedBytes i am getting from a api response, how can i convert them to display in a Image widget
This is the code I tried so far.
var image = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
imageURI = image;
final bytes = image.readAsBytesSync();
String img64 = base64Encode(bytes);
print(bytes);
print(img64);
final decodedBytes = base64Decode(img64);
print(decodedBytes);
//consider i am getting this decodedBytes i am getting from a api response, how can i convert them to display in a Image widget
});
I am getting this error using writeAsBytesSync(),
Unhandled Exception: FileSystemException: Cannot open file, path = 'decodedimg.png'
You get this error, because you can't write to any arbitrary location in an application sandbox. You can use path_provider to look up a temporary directory.
But in your case, just use the image object, pickImage already returns a File object, so just use Image.file(image)
If you want to decode a base64 into a temporary directory you can use:
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as path;
Future<File> writeImageTemp(String base64Image, String imageName) async {
final dir = await getTemporaryDirectory();
await dir.create(recursive: true);
final tempFile = File(path.join(dir.path, imageName));
await tempFile.writeAsBytes(base64.decode(base64Image));
return tempFile;
}
with pubspec.yaml:
dependencies:
path: ^1.6.0
path_provider: ^1.6.7

How to test ImagePicker in Flutter Driver?

In Flutter integration testing, how can we handle ImagePicker? as well as other platform related plugins?
Finally, I got a solution for this question.
this is the code in app.dart:
prepare an image file in assets, for example: images/sample.png.
import 'dart:io';
import 'dart:typed_data';
import 'package:path_provider/path_provider.dart';
import 'package:image_picker_test/main.dart' as app;
import 'package:flutter_driver/driver_extension.dart';
import 'package:flutter/services.dart';
void main() {
// This line enables the extension.
enableFlutterDriverExtension();
const MethodChannel channel =
MethodChannel('plugins.flutter.io/image_picker');
channel.setMockMethodCallHandler((MethodCall methodCall) async {
ByteData data = await rootBundle.load('images/sample.png');
Uint8List bytes = data.buffer.asUint8List();
Directory tempDir = await getTemporaryDirectory();
File file = await File('${tempDir.path}/tmp.tmp', ).writeAsBytes(bytes);
print(file.path);
return file.path;
});
app.main();
}
Frank Yan's solution works fine. Basically he is using MethodChannel as an interceptor of request to ImagePicker
MethodChannel('plugins.flutter.io/image_picker')
In this part he defines which plugin has to be mocked
channel.setMockMethodCallHandler((MethodCall methodCall) async {
ByteData data = await rootBundle.load('images/sample.png');
Uint8List bytes = data.buffer.asUint8List();
Directory tempDir = await getTemporaryDirectory();
File file = await File('${tempDir.path}/tmp.tmp', ).writeAsBytes(bytes);
print(file.path);
return file.path;
});
This function defines what has to be returned from request to image picker plugin. So your program will do these actions each time when user uses image picker. Right here it will just return the image from 'images/sample.png'. In my case I had to put image into assets/image.png in my project root. Anyway you can mock any plugin like that. I had to also mock cropper plugin which is called after image picker ends it's job.
**Note: **mocking is not the best way to go with e2e or as they are called in flutter integration tests. I used it just because there is no workaround (I couldn't find it) at the moment and I am blocked with step of picture upload in my scenario. So be careful with using such approach.
You don't need to call this function anywhere in test. Your app will run with mocked plugin that we define in MethodChannel constuctor MethodChannel('');

JavaFx - Creating animation from Image array

I have array of Image in JavaFx. I want create a clip video (animation) from those images, including sound file.
How Can I achieve this?
NOTE: I want to get a video file at the end of the process (avi, mp4 ...).
This is my array:
Image[] frames
I tried use "keyFrame" class... but without success:
ImageView destImageView = new ImageView();
Group group;
group = new Group();
group.setTranslateX(300);
group.setTranslateY(450);
Image[] frames = m.getFrames();
KeyFrame[] kf = new KeyFrame[frames.length];
for(int i=0;i<frames.length;i++){
kf[0] =new KeyFrame(new Duration(0), new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
// destImageView.setImage();
// group.getChildren().setAll(destImageView);
}
});
}
You can use
javax.imageio.ImageIO.write(javafx.embed.swing.SwingFXUtils.fromFXImage(frame, null), "png", new File(directory, fileName));
to save each image as a png file.
Make sure to give the frames sequentially numbered filenames, e.g. img0000.png, img0001.png etc..
Then use ImageJ/Fiji (https://imagej.net/Fiji/Downloads)
to import the image sequence and save as an avi file. Alternatively, as ImageJ is open-source and written in Java you could import and use directly the ImageJ class
ij.plugin.filter.AVI_Writer
You could then convert it to an mp4 or other format using VLC Player, for example.

Resources