I have a vector which holds byte data (chars) received from a socket. This data holds different datatypes i want to extract. E.g. the first 8 elements (8 Bytes) of the vector are an uint64_t. Now I want to convert these first 8 Bytes to a single uint64.
A workaround I've found is:
// recv_buffer is the vector containing the received Bytes
std::vector<uint64_t> frame_number(recv_buffer.begin(), recv_buffer.begin() + sizeof(uint64_t));
uint64_t frame_num = frame.number.at(0);
Is there a way to extract the data without creating a new vector?
This is an effective method:
C/C++:
uint64_t hexToUint64(char *data, int32_t offset){
uint64_t num = 0;
for (int32_t i = offset; i < offset + 8; i++) {
num = (num << 8) + (data[i] & 0xFF);
}
return num;
}
Java:
long hexToUint64(byte[] data, int offset){
return
((long)data[offset++] << 56 & 0xFF00000000000000L) |
((long)data[offset++] << 48 & 0xFF000000000000L) |
((long)data[offset++] << 40 & 0xFF0000000000L) |
((long)data[offset++] << 32 & 0xFF00000000L) |
((long)data[offset++] << 24 & 0xFF000000L) |
((long)data[offset++] << 16 & 0xFF0000L) |
((long)data[offset++] << 8 & 0xFF00L) |
((long)data[offset++] & 0xFFL);
}
JavaScript:
function hexToUint64(data, offset) {
let num = 0;
let multiple = 0x100000000000000;
for (let i = offset; i < offset + 8; i++ , multiple /= 0x100) {
num += (data[i] & 0xFF) * multiple;
}
return num;
}
One normally uses memcpy or similar to a properly aligned structure, and then ntohl to convert a number from network byte order to computer byte order. ntohl is not part of the C++ specification, but exists in Linux and Windows and others regardless.
uint64_t frame_num;
std::copy(recv_buffer.begin(), recv_buffer.begin() + sizeof(uint64_t), static_cast<char*>(&fame_num);
//or memcpy(&frame_num, recv_buffer.data(), sizeof(frame_num));
frame_num = ntohl(ntohl);
It is tempting to do this for a struct that represents an entire network header, but since C++ compilers can inject padding bytes into structs, and it's undefined to write to the padding, it's better to do this one primitive at a time.
You could perform the conversion byte by byte like this:
int main()
{
unsigned char bytesArray[8];
bytesArray[0] = 0x05;
bytesArray[1] = 0x00;
bytesArray[2] = 0x00;
bytesArray[3] = 0x00;
bytesArray[4] = 0x00;
bytesArray[5] = 0x00;
bytesArray[6] = 0x00;
bytesArray[7] = 0x00;
uint64_t intVal = 0;
intVal = (intVal << 8) + bytesArray[7];
intVal = (intVal << 8) + bytesArray[6];
intVal = (intVal << 8) + bytesArray[5];
intVal = (intVal << 8) + bytesArray[4];
intVal = (intVal << 8) + bytesArray[3];
intVal = (intVal << 8) + bytesArray[2];
intVal = (intVal << 8) + bytesArray[1];
intVal = (intVal << 8) + bytesArray[0];
cout<<intVal;
return 0;
}
I suggest doing the following:
uint64_t frame_num = *((uint64_t*)recv_buffer.data());
You should of course first verify that the amount of data you have in recv_buffer is at least sizeof(frame_num) bytes.
sorry this may be somewhat duplication, but i am not able to fix it. i am involved with handwritten OCR application. I use MNIST digit database for training process here. I use following codehere for read pixels from the database and re-create the image. programs doesnt give any error but it gives meaningless image(totally black and unclear pixel patterns) as output. can someone explain the reason for that? plz help
here is my code
int reverseInt(int i) {
unsigned char c1, c2, c3, c4;
c1 = i & 255;
c2 = (i >> 8) & 255;
c3 = (i >> 16) & 255;
c4 = (i >> 24) & 255;
return ((int)c1 << 24) + ((int)c2 << 16) + ((int)c3 << 8) + c4;
}
void create_image(CvSize size, int channels, unsigned char* data[28][28], int imagenumber) {
string imgname; ostringstream imgstrm;string fullpath;
imgstrm << imagenumber;
imgname=imgstrm.str();
fullpath="D:\\"+imgname+".jpg";
IplImage *imghead=cvCreateImageHeader(size, IPL_DEPTH_16S, channels);
imghead->imageData=(char *)data;
cvSaveImage(fullpath.c_str(),imghead);
}
int main(){
ifstream file ("D:\\train-images.idx3-ubyte",ios::binary);
if (file.is_open())
{
int magic_number=0; int number_of_images=0;int r; int c;
int n_rows=0; int n_cols=0;CvSize size;unsigned char temp=0;
file.read((char*)&magic_number,sizeof(magic_number));
magic_number= reverseInt(magic_number);
file.read((char*)&number_of_images,sizeof(number_of_images));
number_of_images= reverseInt(number_of_images);
file.read((char*)&n_rows,sizeof(n_rows));
n_rows= reverseInt(n_rows);
file.read((char*)&n_cols,sizeof(n_cols));
n_cols= reverseInt(n_cols);
unsigned char *arr[28][28];
for(int i=0;i<number_of_images;++i)
{
for(r=0;r<n_rows;++r)
{
for(c=0;c<n_cols;++c)
{
file.read((char*)&temp,sizeof(temp));
arr[r][c]= &temp;
}
}
size.height=r;size.width=c;
create_image(size,1, arr, i);
}
}
return 0;
}
You have:
unsigned char temp=0;
...
file.read((char*)&temp,sizeof(temp));
With that you are reading a byte into a single char, and overwriting it with each subsequent byte in the file.
When you do this:
create_image(size,3, &temp, i);
temp is only one character long and just contains the last byte in the file, so your image ends up being just whatever happens to be in memeory after temp.
You need to allocate an array to hold the image data and increment a pointer into it as you fill it with data.
Also you are creating a 3 channel image, but the MNIST data is only single channel, right?
Also,
imghead->imageData=(char *)data;
should be
cvSetData(imghead, data, size.width)
and
unsigned char *arr[28][28];
should be
unsigned char arr[28][28];
I also wanted to use MNIST with OpenCV and this question was the closest i got.
I thought I post a "copy&paste->be happy" version based on cv::Mat instead of iplimage, since this is easier to work with. Also, cv::Mat is preferred since OpenCV 2.x.
This method get you a vector of pairs of cv::Mat images and labels as ints. Have fun.
std::vector<std::pair<cv::Mat,int>> loadBinary(const std::string &datapath, const std::string &labelpath){
std::vector<std::pair<cv::Mat,int>> dataset;
std::ifstream datas(datapath,std::ios::binary);
std::ifstream labels(labelpath,std::ios::binary);
if (!datas.is_open() || !labels.is_open())
throw std::runtime_error("binary files could not be loaded");
int magic_number=0; int number_of_images=0;int r; int c;
int n_rows=0; int n_cols=0; unsigned char temp=0;
// parse data header
datas.read((char*)&magic_number,sizeof(magic_number));
magic_number=reverseInt(magic_number);
datas.read((char*)&number_of_images,sizeof(number_of_images));
number_of_images=reverseInt(number_of_images);
datas.read((char*)&n_rows,sizeof(n_rows));
n_rows=reverseInt(n_rows);
datas.read((char*)&n_cols,sizeof(n_cols));
n_cols=reverseInt(n_cols);
// parse label header - ignore
int dummy;
labels.read((char*)&dummy,sizeof(dummy));
labels.read((char*)&dummy,sizeof(dummy));
for(int i=0;i<number_of_images;++i){
cv::Mat img(n_rows,n_cols,CV_32FC1);
for(r=0;r<n_rows;++r){
for(c=0;c<n_cols;++c){
datas.read((char*)&temp,sizeof(temp));
img.at<float>(r,c) = 1.0-((float)temp)/255.0; // inverse 0.255 values
}
}
labels.read((char*)&temp,sizeof(temp));
dataset.push_back(std::make_pair(img,(int)temp));
}
return dataset;
}
just the same as above:
int reverseInt(int i) {
unsigned char c1, c2, c3, c4;
c1 = i & 255; c2 = (i >> 8) & 255; c3 = (i >> 16) & 255; c4 = (i >> 24) & 255;
return ((int)c1 << 24) + ((int)c2 << 16) + ((int)c3 << 8) + c4;
}
Whats the proper way about going about this? Lets say I have ABCD and abcd and the output bits should be something like AaBbCcDd.
unsigned int JoinBits(unsigned short a, unsigned short b) { }
#include <stdint.h>
uint32_t JoinBits(uint16_t a, uint16_t b) {
uint32_t result = 0;
for(int8_t ii = 15; ii >= 0; ii--){
result |= (a >> ii) & 1;
result <<= 1;
result |= (b >> ii) & 1;
if(ii != 0){
result <<= 1;
}
}
return result;
}
also tested on ideone here: http://ideone.com/lXTqB.
First, spread your bits:
unsigned int Spread(unsigned short x)
{
unsigned int result=0;
for (unsigned int i=0; i<15; ++i)
result |= ((x>>i)&1)<<(i*2);
return result;
}
Then merge the two with an offset in your function like this:
Spread(a) | (Spread(b)<<1);
If you want true bitwise interleaving, the simplest and elegant way might be this:
unsigned int JoinBits(unsigned short a, unsigned short b)
{
unsigned int r = 0;
for (int i = 0; i < 16; i++)
r |= ((a & (1 << i)) << i) | ((b & (1 << i)) << (i + 1));
return r;
}
Without any math trick to exploit, my first naive solution would be to use a BitSet like data structure to compute the output number bit by bit. This would take looping over lg(a) + lg(b) bits which would give you the complexity.
Quite possible with some bit manipulation, but the exact code depends on the byte order of the platform. Assuming little-endian (which is the most common), you could do:
unsigned int JoinBits(unsigned short x, unsigned short y) {
// x := AB-CD
// y := ab-cd
char bytes[4];
/* Dd */ bytes[0] = ((x & 0x000F) << 4) | (y & 0x000F);
/* Cc */ bytes[1] = (x & 0x00F0) | ((y & 0x00F0) >> 4);
/* Bb */ bytes[2] = ((x & 0x0F00) >> 4) | ((y & 0x0F00) >> 8);
/* Aa */ bytes[3] = ((x & 0xF000) >> 8) | ((y & 0xF000) >> 12);
return *reinterpret_cast<unsigned int *>(bytes);
}
From Sean Anderson's website :
static const unsigned short MortonTable256[256] =
{
0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015,
0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055,
0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115,
0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155,
0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415,
0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455,
0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515,
0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555,
0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015,
0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055,
0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115,
0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155,
0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415,
0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455,
0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515,
0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555,
0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015,
0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055,
0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115,
0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155,
0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415,
0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455,
0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515,
0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555,
0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015,
0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055,
0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115,
0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155,
0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415,
0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455,
0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515,
0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
};
unsigned short x; // Interleave bits of x and y, so that all of the
unsigned short y; // bits of x are in the even positions and y in the odd;
unsigned int z; // z gets the resulting 32-bit Morton Number.
z = MortonTable256[y >> 8] << 17 |
MortonTable256[x >> 8] << 16 |
MortonTable256[y & 0xFF] << 1 |
MortonTable256[x & 0xFF];