Convert CameraImage Stream to Bytes or File in flutter? - google-mlkit

I am trying to use google ml kit to process an image so i extract the left eye open probability,
but it requires the input image to be either a file,bytes or file path, see below
final inputImage = InputImage.fromFile(file);
final inputImage = InputImage.fromBytes(bytes: bytes, inputImageData: inputImageData);
final inputImage = InputImage.fromFilePath(filePath);
it requires one of those above, i am trying to use a Camera image stream to achieve this,
_cameraService.cameraController.startImageStream((image) async {
// i am trying to convert the image received here to be converted into either a File, Bytes, File path
}

ML Kit team doesn't own the flutter_mlkit repo, so please file issue at https://github.com/azihsoyn/flutter_mlkit/issues

Related

Converting image files to VARBINARY(max) in flutter

I need to store images that are captured using "image picker" in a SQL server database
final image = await ImagePicker().pickImage(source: ImageSource.camera, imageQuality: 25);
now, I know that the images should be stored in a "VARBINARY" datatype. I tried to convert the XFile "image" that I got from the "ImagePicker()" to VARBINARY and these are the steps I made.
final image = await ImagePicker().pickImage(source: ImageSource.camera, imageQuality: 25);
var imageTemp = File(image.path);
and then I store the image in the database using the following.
Attachment(
attachmentData: base64Encode((imageTemp .readAsBytesSync())),
attachmentName: imageTemp .path.split('/').last,
attachmentSize: imageTemp .readAsBytesSync().lengthInBytes,
attachmentType: imageTemp .path.split(".").last,
)
"attachmentData: base64Encode((imageTemp .readAsBytesSync()))"
"attachmentData is a String"
So from XFile to VARBINARY, I had done the following
final image = await ImagePicker().pickImage(source: ImageSource.camera, imageQuality: 25);
var imageTemp = File(image.path);
base64Encode((imageTemp .readAsBytesSync())) //the sent data
when I print the data after the readAsByteSynce() it starts with [255,216,.255,..] which is FF D8 FF
it looks like this
screen shot of print(imageTemp.readAsBytesSync())
and when I print the image after using base64Encode it starts with /9j/4Q
it looks like this
screen shot of print(base64Encode((imageTemp.readAsBytesSync())))
now when it's stored in the SQL server database it starts with 0x2F39
it looks like this screen shot of the attachmebtData field in the SQL server database
The image extension is .jpg. Shouldn't jpg images start with 0xFF?
I need to take these images and view them in ArcGIS and when I open the image it says that the images are not in a supported format.
can someone please tell me what am I doing wrong and why are my jpg images starts with 0x2F in the database and not 0xFFD8FF and how to fix this?
I want the image to be stored in the database
I also Tried converting Uint8List to hex using dart package hex 0.2.0
which converted it to this the output of print(Hex.encode(await image.readAsBytes))
as you can see in the above picture it starts with ffd8ff which is the correct format for jpg pictures, but when I send this to the database it looks like it converts these letters to VARBINARY and the output starts with 0x666666 and looks like this image from SQL server AttachmentData field when Hex.encode data was sent to it
The problem was that I'm not decoding it in the backend before inserting it into the database.
I'm Using Python "FAST API" and I needed to write the following line to attachmentdata before inserting it into the database.
attachment.attachmentData = base64.decodebytes(attachment.attachmentData)

MS Cognitive custom voice-submitting sample data-returning "Only the RIFF(WAV) format is accepted. Check the format of your audio files."

Just checking to make sure that this should be supported. The page here says that you should be able to use any PCM file that's at least 16kHz. I'm trying to segment a longer wav file into utterances using NAudio, and I can generate the files, but all of the training data that I submit is coming back with the processing error "Only the RIFF(WAV) format is accepted. Check the format of your audio files." The audio files are 16 bit PCM, mono, 44kHz wav files, and are all under 60s. Is there another constraint on the file format that I might be missing? The wav files do have a valid RIFF header (verified that the bytes exist).
I managed to figure this out by explicitly re-encoding audio that I received back from the SpeechRecognizer. Definitely not an efficient solution, but this was just a hack to test things out. Here's the code for reference (put this in Recognizer.Recognized):
string rawResult = ea.Result.ToString(); //can get access to raw value this way.
Regex r = new Regex(#".*Offset"":(\d*),.*");
UInt64 offset = Convert.ToUInt64(r?.Match(rawResult)?.Groups[1]?.Value);
r = new Regex(#".*Duration"":(\d*),.*");
UInt64 duration = Convert.ToUInt64(r?.Match(rawResult)?.Groups[1]?.Value);
//create segment files
File.AppendAllText($#"{path}\{fileName}\{fileName}.txt", $"{segmentNumber}\t{ea.Result.Text}\r\n");
//offset and duration are in 100ns units
WaveFileReader w = new WaveFileReader(v);
long totalDurationInMs = w.SampleCount / w.WaveFormat.SampleRate * 1000; //total length of the file
ulong offsetInMs = offset / 10000; //convert from 100ns intervals to ms
ulong durationInMs = duration / 10000;
long bytesPerMilliseconds = w.WaveFormat.AverageBytesPerSecond / 1000;
w.Position = bytesPerMilliseconds * (long)offsetInMs;
long bytesToRead = bytesPerMilliseconds * (long)durationInMs;
byte[] buffer = new byte[bytesToRead];
int bytesRead = w.Read(buffer, 0, (int)bytesToRead);
string wavFileName = $#"{path}\{fileName}\{segmentNumber}.wav";
string tempFileName = wavFileName + ".tmp";
WaveFileWriter wr = new WaveFileWriter(tempFileName, w.WaveFormat);
wr.Write(buffer, 0, bytesRead);
wr.Close();
//this is probably really inefficient, but it's also the simplest way to get things in the right format. It's a prototype-deal with it...
WaveFileReader r2 = new WaveFileReader(tempFileName);
//from other project
var desiredOutputFormat = new WaveFormat(16000, 16, 1);
using (var converter = new WaveFormatConversionStream(desiredOutputFormat, r2))
{
WaveFileWriter.CreateWaveFile(wavFileName, converter);
}
segmentNumber++;
This splits the input file to separate per-turn files, and appends the turn transcripts in the text file using the filenames.
The good news is that this produced a "valid" dataset, and I was able to create a voice from it. The bad news is that the voice font produced audio that was almost completely unintelligible, which I'm going to attribute to a combination of using machine-transcribed samples along with irregular turn breaks and possibly noisy audio. I may see if there's anything that can be done to improve the accuracy by hand editing a few files, but I at least wanted to post an answer here in case anyone else has the same problem.
Also, it appears that either 16 KHz and 44 KHz PCM will work with custom voice, so that's a plus if you have higher quality audio available.

Google Drive - use WebViewLink vs thumbnailLink

I'm using the Google Drive API where I can gain access to 2 pieces of data that I need to display a jpg file oin my program. WebViewLink is the "large" size image while thumbnailLink is the "thumb" smaller size of the same image.
I'm having an issue with downloading the WebViewLink that I do not have with the thumbnailLink. Part of my code calls either exif_imagetype($filename) or getimagesize($filename) so I can retrieve the type, height & width etc for the $filename. This is successful for the thumbnailView but not the WebViewLink...
code snippet...
$WebViewLink = "https://drive.google.com/a/treering.com/file/d/blablabla";
$type = exif_imagetype($WebViewLink);
--- results in the error
"PHP Warning: exif_imagetype(): stream does not support seeking..."
where as...
$thumbnailLink = "https://lh6.googleusercontent.com/blablabla";
$type = exif_imagetype($thumbnailLink);
--- successful
where $type = 2 // a .jpg file
Not sure what I need to do to gain a usable WebViewLink... maybe use the "export" function to copy to a file on my server that is accessible, then use that exported file for the functions that fail above?
Thanks for any help.
John
I think you are using the wrong property to get the image of the file.
WebViewLink
A link for opening the file in a relevant Google editor or viewer in a browser.
thumbnailLink
A short-lived link to the file's thumbnail, if available. Typically lasts on the order of hours.
You can try using the iconLink():
A static, unauthenticated link to the file's icon.
Sample image of thumbnailLink:
Sample image of a iconLink:
It will still show relevant image about the file.
Hope it helps!

Jcrop and imagemagic final piece of puzzle

I have set up on client Jcrop and on Server a imagemagick (express.js).
Image is uploaded to server first, and then shown to the client. Client makes crop, and the following information is sent to server:
function showCoords(c)
{
// variables can be accessed here as
// c.x, c.y, c.x2, c.y2, c.w, c.h
};
I have the image stored on server ready to be cropped. Question is, if using imagemagick... how do I use those variables? Image magick has resize and crop (it has other options as well) that seem to be relevant... but it seems that I have more variables then the IM accepts.
What is going on?
You can ignore point2 (c.x2,x.y2). Jcrop is just being helpful by giving you a rectangles size (c.w,c.h), starting point (c.x,c.y), and ending point (c.x2,c.y2).
ImageMagick has it's own Image Geometry format, so you just need the size & offset (starting point).
function showCoords(c)
{
var IMGeometry = String.concat(c.w,"x",c.y,"+",c.x,"+",c.y);
//=> "175x125+50+50"
// Assuming you are using node-imagemagick
im.convert(["source.jpg","-crop",IMGeometry,"out.jpg"],function(err, stdout){
// Callback
});
}

Mimic file IO in j2me midlet using RMS

I want to be able to record audio and save it to persistent storage in my j2me application. As I understand j2me does not expose the handset's file system, instead it wants the developer to use the RMS system. I understand the idea behind RMS but cannot seem to think of the best way to implement audio recording using it. I have a continuous stream of bits from the audio input which must be saved, 1) should I make a buffer and then periodically create a new record with the bytes in the buffer. 2) Should I put each sample in a new record? 3) should I save the entire recording file in a byte array and then only write it to the RMS on stop recording?
Is there a better way to achieve this other than RMS?
Consider this code below and edit it as necessary it should solve your problem by writing to the phone filesystem directly
getRoots();
FileConnection fc = null;
DataOutputStream dos = null;
fc = (FileConnection)Connector.open("file:///E:/");
if (!fc.exists())
{
fc.mkdir();
}
fc = (FileConnection) Connector.open("file:///E:/test.wav");
if (!fc.exists())
{
fc.create();
}
dos = fc.openDataOutputStream();
dos.write( recordedSoundArray);