I am using the OpenCV library, which has a class called Mat, representing a matrix, with data stored in an array at uchar* Mat::data. I want to write this data to a binary file using C++.
Here is my code:
cv::Mat m(3, 3, CV_8UC1); // This basically creates a 3-by-3 matrix
std::fstream fileOut("file.bin", std::ios::out | std::ios::binary);
fileOut.write((char*)m.data, 9); // This should write 9 bytes of data
And I am getting the error message:
invalid conversion from ‘uchar* {aka unsigned char*}’ to ‘std::basic_istream<char>::char_type* {aka char*}’
What should I do differently?
it's an illegal conversion in C++
use reinterpret_cast<const char*>(m.data)
Related
In lesson_02_input_image.cpp, I am trying to transpose Buffer<uint8_t> type data to a c++ array so that compare the time consumption between halide and c++. The code is like :
Halide::Buffer<uint8_t> input = load_image("images/rgb.png");
float *img = input.copy_to_device(halide_opencl_device_interface());
And the code got error:cannot convert ‘Halide::Buffer’ to ‘float*’ in initialization.It seems that input is Halide::Buffer type, how could I fix that?
I am trying to convert an uint32_t* into a format that could be accepted by a Mat object (from open cv). I do not need to display the data from the Mat, I am simply using the mat to transport and pack information.I know that opencv does not use uint32_t and as a workaround I used int. What I did is the following:
Mat package = Mat(width,height, CV_32SC4);
int *dst1 = package.data;
//code that works with the dst
//finally put it back in the package
package.data = dst1;
The above code gives me an error at the second line. (Cannot convert from 'int *' to 'uchar *')
So far I have code to read an unsigned char from ifstream:
ifstream in;
unsigned char temp;
in.open ("RANDOMFILE", ios::in | ios::binary);
in.read (&temp, 1);
in.close ();
Is this correct? I also tried to write an unsigned char to an ofstream:
ofstream out;
unsigned char temp;
out.open ("RANDOMFILE", ios::out | ios::binary);
out.write (&static_cast<char>(temp), 1);
out.close ();
But I get the following error for writing:
error C2102: '&' requires l-value
And this error for reading:
error C2664: 'std::basic_istream<_Elem,_Traits>::read' : cannot convert parameter 1 from 'unsigned char *' to 'char *'
It would be appreciated if someone could tell me what's wrong with my code or how I can read and write unsigned chars from fstream.
The write error is telling you that you are taking the address of the temporary created by static_cast.
Instead of:
// Make a new char with the same value as temp
out.write (&static_cast<char>(temp), 1);
Use the same data already in temp:
// Use temp directly, interpreting it as a char
out.write (reinterpret_cast<char*>(&temp), 1);
The read error will also be fixed if you tell the compiler to interpret the data as a char:
in.read (reinterpret_cast<char*>(&temp), 1);
The read function always takes bytes as arguments, represented as char values for convenience. You can cast the pointer to these bytes around as much as you want, so
in.read (reinterpret_cast<char*>(&temp), 1);
will read a single byte just fine. Remember that memory is memory is memory, and the types of C++ are just an interpretation of memory. When you are reading raw bytes into raw memory (as with read), you should read first and then cast to the appropriate type.
I am using an HDF5 library to read data from an HDF5 file in c++ and the call I am having problems with is the following:
status = H5Dread(
hdf5_dataset,
hdf5_datatype,
hdf5_dataspace_in_memory,
hdf5_dataspace_in_file,
H5P_DEFAULT,
buf
);
The last argument is supposed to be a void pointer, and I have a vector of floats that I want to be allocated, however when I try to pass the vector g++ gives me the following error:
error: cannot convert ‘std::vector<float, std::allocator<float> >’ to ‘void*’ for argument ‘6’ to ‘herr_t H5Dread(hid_t, hid_t, hid_t, hid_t, hid_t, void*)’
Is there any way that I can write directly to the vector without having to allocate the memory twice?
As std::vector guarantees the data is stored in contiguous memory, you can convert a vector to a pointer like so:
std::vector<float> myFloats;
void *ptr = static_cast<void*>(&myFloats[0]); // or &myFloats.front()
Edit: if you are writing to it without calling push_back, make sure you resize enough space first!
Given a std::vector<float>, you can obtain a pointer to the contiguous buffer of floats thus:
std::vector<float> v;
fillMyVectorSomehow(v);
float* buffer = &v[0]; // <---
You could cast this to void* and pass it through.
Ok. With a help of SO I have managed to put together this code. There is one more error though:
// ...
std::vector<char> jpegBuffer(lSize);
// copy the file into the buffer.
fread(&jpegBuffer[0], 1, jpegBuffer.size(), pFile);
// terminate
fclose (pFile);
Mat matrixJpeg = cv::imdecode(Mat(jpegBuffer), 1);
IplImage fIplImageHeader = matrixJpeg;
cvShowImage("Video", fIplImageHeader);
char key = cvWaitKey();
There is one more error with this code though. It is at this line:
cvShowImage("Video", fIplImageHeader);
And the error is:
/home/richard/Desktop/richard/client/src/main.cc:106: error: cannot convert ‘IplImage’ to ‘const CvArr*’ for argument ‘2’ to ‘void cvShowImage(const char*, const CvArr*)’
According to the docs Mat and IplImage should be interchangable and this:
IplImage fIplImageHeader = matrixJpeg;
Should be all that is needed to convert Mat to IplImage.
I think it should be:
IplImage* fIplImageHeader = matrixJpeg;
IplImage* and Mat* should be interchangeable.
CvArr* is a typedef for void*
You must specify the forced type conversion:
csShowImage("Whatever", static_cast<CvArr*>(somePointer));
Also note that somePointer is a pointer.
You might say something like
IplImage object = matrix;
IplImage* somePointer = &object;
Also, I kind of doubt it that arbitrary image type is substitutable with a matrix type. What are you willing to achieve when you tell your program to show the matrix?