I try to make an application in unity, using OpenCV. I need the Absdiff from two pictures.
My Problem is that I get an OpenCvSharp.OutputArray from the Cv2.Absdiff(processImageTwo, processImageOne, differenceImage); function and I cant't convert it to a byte[], which I'll need to store the image.
Can somebody help me, how to convert an OpenCvSharp.OutputArray to byte?
Please try:
byte[] bytes = differenceImage.GetMat().ToBytes();
This should convert the image to png byte format.
See https://shimat.github.io/opencvsharp_docs
Related
I am trying to convert YUV420 frames to Bitmap or Image. I am reading these frames from an MP4 video in C# using the AVBlocks library. So, after creating an input and output socket using AVBlocks classes, I then pull each frame from the video with a YUV420 color format and UncompressedVideo stream type. I basically do this by calling Transcoder.Pull(int outputIndex, MediaSample outputData) and then the MediaBuffer that's part of the outputData has the data in an array of bytes. So I am trying to convert these bytes to a Bitmap or Image so that I can eventually show each frame into a PictureBox in the Winforms application.
What I've tried:
I have tried using a MemoryStream, as shown below, but I get an unhandled ArgumentException saying that the parameter is not valid. I tried using ImageConverter() as well to convert to an Image, but I get the same exception. Then, I converted the byte array from YUV to RGB format and gave the updated array as a parameter to the MemoryStream, but again no luck. I also tried changing the color format of the output socket from YUV420 to a BGR format, but it resulted in the same issue as above. The code that tries to convert to a bitmap using MemoryStream:
while (transcoder.Pull(out inputIndex, yuvFrame))
{
buffer = (MediaBuffer) yuvFrame.Buffer.Clone();
Bitmap b;
byte[] temp = new byte[buffer.DataSize];
Array.Copy(buffer.Start, buffer.DataOffset, temp, 0, buffer.DataSize);
var ms = new MemoryStream(temp);
b = new Bitmap(ms);
}
The aforementioned exception is thrown in the last line of the code. I'm not sure if it's the color format or the stream type, or something else that's causing the problem. If someone wants to see more of the code (setting up input & output sockets etc), let me know. For reference, the link to the example I've been following from AVBlocks is this and the link to MediaBuffer class is this.
The Bitmap(MemoryStream ms) constructor expects the bytes from an actual file, like a png, jpeg, bmp or gif. If I'm reading this correctly, you don't have that; you only have pure RGB triplets data. That isn't enough, because it lacks all information about the image's width, height, colour depth etc.
You will need to actually construct an image object from the RGB data. This isn't really trivial; it means you need to make a new image object with the correct dimensions and colour format, then access its backing bytes array, and write your data into it. The actual code for creating an image out of a byte array can be found in this answer.
Note that you'll have to take into account the actual stride in the resulting data you get; the amount of bytes on each line of the image. Images are saved per line, and those lines are usually padded to a multiple of 4 bytes. This obviously messes up a lot if you don't take it into account.
If your data is completely compact, then the stride to give to the BuildImage function I linked to will just be your image width multiplied by the amount of bytes per pixel (should be 3 for 24bpp RGB), but if not, you'll have to pad it to the next multiple of 4.
I'm using the C# to convert Images into Bytes or other formats(like Base64) and I'll store them to SQL Server database.Using web service(REST) I would like to get that encoded data and to display as an Image in Android. My Major doubt is that the Bytes or Base64 in the C# same as in the Android ?. Anybody,please give me a suggestion.
They both should work cross language since they're just a serializable representation of the file contents, no real language specific stuff.
For the bytes, you can use the BitmapFactory to get an image in android, and to convert a base64 encoded image to a bitmap, you can use this to get a byte-array and the use the BitmapFactory
byte[] decodedString = Base64.decode(encodedImage, Base64.DEFAULT);
I need to convert an picture (that is stored in an object of type Image) to a string for storage (and later for conversion back into an Image object for display) in a metro app
I have found lots of answers for converting an image to a base64 string in .NET 4.0 etc but in 4.5 the System.Windows.Bitmap namespace isn't there (the Image class is in Windows.UI.Xaml.Media.Imaging) and the method that was in that namespace that made it possible in 4.0 "Save()" doesn't seem to be in 4.5...unless I just can't find it.
Theres an example of doing this here but like I said it doesn't work in a metro app/.NET 4.5
any ideas?
more details:
the method that will do this will convert an instance field that contains an image object (ive used its source property, is this correct?) and needs to store the resultant string from the conversion in an instance string field. this whole object can then be serialized, ignoring the Image field, with the hope of deserializing later and restoring the string to the Image field for display. so far ive tried to use a DataContractSerializer to serialize string from the image, but it doesn't seem to like it. Once I get a string from the image I would be able to serialize that, but its not something I've ever done before.
Also, it seems that the only .net 4.5 documentation that is definitely correct is the pages here: http://msdn.microsoft.com/library/windows/apps/
pages at the "normal looking" msdn site for .net 4.5 don't seem to always work in metro apps? (just a theory?)
[solved]
I finally got it! for anyone else that ever has to do this the answer is here: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/38c6cb85-7454-424f-ae94-32782c036567/
I did this
var reader = new DataReader(myMemoryStream.GetInputStreamAt(0));
var bytes = new byte[myMemoryStream.Size];
await reader.LoadAsync((uint)myMemoryStream.Size);
reader.ReadBytes(bytes);
after this sequence, the byte array bytes will have the data from the stream in it, from there I set a string to the value of
Convert.ToBase64String(bytes);
I finally got it! for anyone else that ever has to do this the answer is here: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/38c6cb85-7454-424f-ae94-32782c036567/
I did this
var reader = new DataReader(myMemoryStream.GetInputStreamAt(0));
var bytes = new byte[myMemoryStream.Size];
await reader.LoadAsync((uint)myMemoryStream.Size);
reader.ReadBytes(bytes);
after this sequence, the byte array bytes will have the data from the stream in it, from there I set a string to the value of
Convert.ToBase64String(bytes);
I'm not sure of this because I do not have the .net 4.5 installed here, but I think this could work:
You could use the BitmapSource.CopyPixels() method to extract the pixels of the image:
http://msdn.microsoft.com/en-us/library/ms616043(v=vs.110).aspx
Then use Convert.ToBase64String() to do the convertion.
Also, here are some useful imaging HOW-TOs:
http://msdn.microsoft.com/en-us/library/ms750864(v=vs.110)
Try BitmapEncoder. Example of how to create a BitmapEncoder here. The appropriate namespace is Windows.Graphics.Imaging.
BitmapEncoder gets you an encoder. You can then use GetPixelDataAsync(BitmapPixelFormat, BitmapAlphaMode, BitmapTransform, ExifOrientationMode, ColorManagementMode) to get your pixel data. Following that you can use any generic C# base64 encoder.
(Examples are Javascript but should work for C# as well since the classes exist in C#)
You should store the encoded format of image (say JPEG) format, decoded back to byte[], create a MemoryStream, then Metro BitmapImage can be created from the stream.
I'm trying to produce a system which takes an image in OpenCV, writes it to XML, reads it from XML, and displays it in an Image control in a WPF application.
The problem I'm having is that I'm unclear as to how .NET classes (e.g. BitmapImage) process images from a byte array. I've tried a number of methods and gotten various errors - too numerous to post unless required.
I was wondering if someone could point me in the right direction regarding this? What I want to know is how does the data need to be presented to a .NET object in order to display it in an Image control?
Thanks in advance for your help - it is much appreciated.
EDIT: I expect what I need to do is convert the XML into a byte array and use that, along with a definition of the format, to instantiate a BitmapImage object or equivalent to use as source for the Image control. What I'm not sure of is how to do this.
Use int cvSaveImage(const char* filename, const CvArr* image)
to save the file as an Image.The image format is chosen based on the filename extension
No need to store it in XML if you can directly store it as Image file.
The .NET classes requires an Image.That's it.
Note:
If you want to store red,green,blue values as comma separated strings, it would be very inefficient.Save it in Base64 instead.You can then convert it into bytes and feed it to any .NET image class.Also the .NET ImageConverter Class may be very helpful.
I found that the issue was (presumably) that I wasn't Base64 encoding the XML data before writing it. Thus the solution is to Base64 encode the data before writing to XML, Base64 decoding it on the other side, reading the data as a byte array and using that to instantiate a MemoryStream and then a BitmapImage object.
Thanks for your help everyone.
You can use:
public static BitmapSource Create(
int pixelWidth,
int pixelHeight,
double dpiX,
double dpiY,
PixelFormat pixelFormat,
BitmapPalette palette,
Array pixels,
int stride
)
I need to get the BitmapImage from the byte array. Currently I'm working with MemoryStream
(byte[] -> MemoryStream -> BitmapImage) but it seems to be not efficient.
The same situation in the other way round - I need to get the byte array representing the BitmapFrame. Again, I'm doing that with MemoryStream.
What is the most efficient way to accomplish that task? Is it possible to speedup the conversion?
Thank you in advance for the replies and hints!
Cheers
Im using BitmapSource.CopyPixels to extract the bytes from the BitmapSource and then BitmapSource.Create to create a new image from the byte array.
I'm not sure how effective it is though, but it is sufficient for my purposes (I can extract the pixels, recolor them and then paste them back on a 2000*2000 image with barely noticeable delay).