How to extract opencv Mat header? - c++

Hi I want to send OpenCV Mat images to a ftp server and the input to my ftp function is uchar *
I have access to data part of Opencv images by using .data method but I don't know how to acess to header information to put is infront of .data and send the whole as a complete image. So I need to extract the header information of OpenCV Mat structure.
I also need to add some information to the header about the image and change the whole header + data to uchar * so that I can send it through. I need something like this:
cv::Mat Myimage(100,100,CV_8UC1,cv::Scalar::all(0));
uchar * Myimagedata = Myimage.data;
uchar * Myimageheader = Header_Extractor(Myimage);
uchar * Complete_Image = Myimageheader + Myimagedata;
SEND_FTP(Complete_Image);

why not send a png or jpg encoded image ? you should prefer this to your current approach for a couple of reasons:
it comes with a builtin protocol already
please, never send uncompressed pixels over a network
what would your poor ftp server do with a cv::Mat ?
vector<uchar> buffer;
imencode(".png", MyImage, buffer);
SEND_FTP(&(buffer[0]));
hmm, wait, that would need a send function, where you can pass the length, too. your SEND_FTP func probably tries strlen, which won't work on binary data. (same problem with your original idea, btw)
also, you will have to switch the ftp connection to binary mode.
i highly doubt, that you really want a cv::Mat serialized to an ftp server (how would that get saved on the other side, even?), but if you want to send one, you might be better off, not sending the complete Mat header(it's a complex beast), but something more simple, like rows,cols,type, data (and make sure, your Mat isContinous()).

Related

How to convert a string into a Standard C File ?

Hi I have an image in my memory and I want to sent it through an external FTP library.
This FTP library accepts only and only standard C FILE and the sample codes provided by this library reads data only from hard disk. In my application I don't want to store my images in the hard disk and then read them using FILE variable, instead I want to do the conversion in my memory so it's faster and more professional.
My image is in the form of uchar * but I can change it to std::String or QByteArray or any other type of string. Now I want to know how can I have a file which is filled by my image data so I will get rid of storing it into the hard disk and read it again.
My pseudo code:
uchar * image = readImage();
FILE * New_Image = String2FileConverter(image); //I need this function
FTP_Upload(New_Image);
On Posix systems, you can use fmemopen to create a memory-backed file handle.

How to convert a cv::mat header and data part into a single qbytearray?

I want to use Qftp module of Qt 4.8.1 to send opencv images to a FTP server. I wrote the following code:
ftp = new QFtp(this);
//ftp initilization
.
.
.
.
//
cv::Mat InputImage(100,100,CV_8UC1,cv::Scalar::all(75));
QImage FTP_Result = QImage((const uchar *) InputImage.data, InputImage.cols, InputImage.rows, InputImage.step, QImage::Format_Indexed8);
QByteArray byteMe((char *) FTP_Result.bits());
qDebug()<<"Image size is: "<<FTP_Result.height()<<"*"<<FTP_Result.width(); //it returns 100*100
ftp->put(byteMe,"Sample.jpg");
When I go into the ftp server hard disk I find Sample.jpg, and it is filled with "K" character which is the Asci equivalent of "75". It seems the header is missing so the operating system thinks it is just a simple text file. I think this is because I only copied InputImage.data into the QByteArray variable so no information about the image is available. what should I do to copy "InputImage" header information into the "byteMe" variable so I could store a healthy JPEG file ?
Try
QByteArray byteMe((char *) FTP_Result.bits(), FTP_Results.byteCount());
When you construct with a simple char * its going to look for a null terminated string.

How do I load an image (raw bytes) with OpenCV?

I am using Mat input = imread(filename); to read an image but I'd like to do it from memory instead. The source of the file is from an HTTP server. To make it faster, instead of writing the file to disk and then use imread() to read from it, i'd like to skip a step and directly load it from memory. How do I go about doing this?
Updated to add error
I tried the following but I'm getting segmentation fault
char * do_stuff(char img[])
{
vector<char> vec(img, img + strlen(img));
Mat input = imdecode(Mat(vec), 1);
}
See the man page for imdecode().
http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#imdecode
I had a similar problem. I needed to decode a jpeg image stream in memory and use the Mat image output for further analysis.
The documentation on OpenCV::imdecode did not provide me enough information to solve the problem.
However, the code here by OP worked for me. This is how I used it ( in C++ ):
//Here pImageData is [unsigned char *] that points to a jpeg compressed image buffer;
// ImageDataSize is the size of compressed content in buffer;
// The image here is grayscale;
cv::vector<unsigned char> ImVec(pImageData, pImageData + ImageDataSize);
cv:Mat ImMat;
ImMat = imdecode(ImVec, 1);
To check I saved the ImMat and was able to open the image file using a image viewer.
cv::imwrite("opencvDecodedImage.jpg", ImMat);
I used : OpenCV 2.4.10 binaries for VC10 on x86.
I hope this information can help others.

OpenCV - return file type for a Mat

I have some code that I am using cv::imdecode(Mat(buf), -1); where buf is a vector created from a char* to give me a Mat object from some raw data (in this case, I happen to know it is jpeg ahead of time).
is there anyway to get from the cv libraries what the original data type is of the buf (in this case I know its jpeg, but I dont want to hardcode that in) ? In other words, I would like to reverse this process with cv::imencode() and pass the same type of data back to the caller.
tldr: I want to be able to decode a raw data buffer into a cv::Mat, do some work, and then encode it back to a raw data buffer in it's original incoming format.

Using openCV to read an image from Amazon S3

I am aware that there are multiple C++ libraries to access data from Amazon S3, using cURL. Using them I can download an image to the local machine, read it into OpenCV, and delete the original file.
But, I was wondering if it would be possible to read an image directly from S3 into OpenCV directly as say, a Mat object.
Would anyone be able to help me accomplish this?
Use cv::imdecode, which will load a buffer with some image data (png, jpeg, etc.) from memory into a matrix.
// Suppose that a std::vector<char> contains the data loaded by Curl.
std::vector<char> data;
// The template<typename T> explicit cv::Mat::Mat(const std::vector<T>& vec)
// constructor gives this vector a cv::Mat header.
cv::Mat data_mat(data);
// Now use cv::imdecode to decode the image to a BGR matrix.
cv::Mat image(cv::imdecode(data_mat));
So, this is what I had to do, as far as the Poco side of it goes.
std::auto_ptr<std::istream> pStr(URIStreamOpener::defaultOpener().open(uri));
StreamCopier::copyToString(*pStr.get(), str);
This would get the image from the supplied URI into the string str without any intermediate storage. The rest is as Kristoff explained.