0

OpenCV uses floats to store SIFT descriptors, where actually it is integer values from 0 to 255. I am using OpenCvSharp, which is a C# wrapper for OpenCV and I would like to convert the float-based descriptors to byte[] because it takes only 1/4 of the space. Before I realized that, I was converting the float[] to byte[] like this to store the descriptors in a database:

float[] floatDescriptor = ...;
byte[] byteDescriptor = new byte[floatDescriptor.Length * sizeof(float)];
Buffer.BlockCopy(floatDescriptor, 0, byteDescriptor, 0, byteDescriptor.Length);

This was very fast, because I could copy the whole float array without any transformation into a byte array. But it takes 4 times more space than this:

float[] floatDescriptor = ...;
byte[] byteDescriptor = new byte[floatDescriptor.Length];
for (int i = 0; i < floatDescriptor.Length; ++i)
{
    byteDescriptor [i] = (byte)floatDescriptor[i];
}

But this is a lot slower. Is there a faster way to do it?

Edit

I am aware of the fact, that two different things are happening there. I'm just wondering if there is some kind of faster way for batch processing casts in arrays. Like Buffer.BlockCopy() is faster than BitConverter.GetBytes(float) for every float in an array.

Miki
  • 40,887
  • 13
  • 123
  • 202
Ben
  • 4,486
  • 6
  • 33
  • 48
  • Linq is not faster than for loops but the following does work : byte[] bytes = (new float[] { 1.0F, 2.0F, 3.0F }).SelectMany(x => BitConverter.GetBytes(x)).ToArray(); – jdweng Dec 21 '20 at 10:50
  • 1
    In the first code block you didnt parse to a smaller type... therfore it was just copying the data from one place to another. In the second codeblock you parse the type from a float to a byte therefore it is natural that this procedure takes longer. I dont think that there is a faster way to archieve this than the one you mentioned. – Nathaniel Walser Dec 21 '20 at 10:51
  • 1
    You want to cast `float[]` to `int[]`, but your first code is not _casting_ `float` to `byte`, it just strore each `float` in 4 `byte` – vasily.sib Dec 21 '20 at 10:54
  • @NathanielWalser yes, I am aware of that. I am not expecting to get the same speed and I'm also kind of expecting, that there is no faster way. But maybe there is one I don't know of, so I thought I'd better ask. – Ben Dec 21 '20 at 11:36
  • @vasily.sib same answer as above. I just wanted to be clear about the fact that I didn't want a byte representation of a float. But I was wondering if there was some kind of batch processing for that kind of task, which might be faster than my solution. – Ben Dec 21 '20 at 11:44
  • Is this speed difference really important? I mean, for small arrays it won't make any appreciable difference, only if we're talking about hundreads of MBs. – Alejandro Dec 21 '20 at 12:50
  • 1
    Have you read https://stackoverflow.com/questions/619041/what-is-the-fastest-way-to-convert-a-float-to-a-byte ? – Caius Jard Dec 21 '20 at 12:56
  • @CaiusJard the suggested answer for the question you posted is exactly what I did before. But this just returns a byte representation of floats. It doesn't actually cast every single float to a single byte. – Ben Dec 21 '20 at 14:12
  • 1
    @Alejandro it's in the magnitude of GB. Actually, one of the reasons why I am looking for an improvement is the limitation of byte[] to a size of Int32.MaxValue. I can store 4 times more information in the same byte array, if I convert the floats to bytes instead of using a byte representation of a float. – Ben Dec 21 '20 at 15:27
  • "Store the descriptors in a database" - is the float-byte conversion really the slowest part of the process? – Caius Jard Dec 21 '20 at 19:55
  • I think you need to add more detail about what you do with the bytes after conversion – Caius Jard Dec 22 '20 at 07:14

0 Answers0