Using openCV to read an image from Amazon S3 - c++

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.

Related

Transfer images on websocket by using boost library

I want to transfer image data on websocket by using boost library.
How should I resolve below error?
At first, I confirmed to be able to transfer and receive text data by referring following URL.
https://www.boost.org/doc/libs/1_68_0/libs/beast/doc/html/beast/quick_start.html
And next, although I tried to transfer image, I got following error message.
websocket_client.cpp:563:38: error: no matching function for call to 'buffer(cv::Mat&)'
ws.write(boost::asio::buffer(img));
What I did are below.
read image file as 'img' by using opencv.
Change the code for transfer data
// Send the message
// ws.write(boost::asio::buffer(std::string(text)));
ws.write(boost::asio::buffer(img));
cv::Mat is not a buffer type or adaptable as such. If you have POD data, then you can "cast" it like the commenter says:
// don't do this:
buffer(&img, sizeof(img));
However, that's not safe:
static_assert(std::is_standard_layout_v<cv::Mat>);
static_assert(std::is_trivial_v<cv::Mat>);
The type is actually not bitwise copyable. But since there's a matrix, there is likely a contiguous region of data that is:
ws.write(net::buffer(img.data, img.total() * img.elemSize()));
This uses total() and elemSize(), links to the documentation.
Now, this will be enough if the receiving end already knows the dimensions. If not, send them first, e.g.:
uint32_t dimensions[] { htonl(image_witdh), htonl(image_height) };
std::vector<net::const_buffer> buffers {
net::buffer(dimensions),
net::buffer(img.data, img.total() * img.elemSize())
};
ws.write(buffers);

How to extract opencv Mat header?

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()).

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.

converting a binary stream into a png format

I will try to be clear ....
My project idea is as follow :
I took several compression algorithms which I implemented using C++, after that I took a text file and applied to it the compression algorithms which I implemented, then applied several encryption algorithms on the compressed files, now I am left with final step which is converting these encrypted files to any format of image ( am thinking about png since its the clearest one ).
MY QUESTION IS :
How could I transform a binary stream into a png format ?
I know the image will look rubbish.
I want the binary stream to be converted to a an png format so I can view it as an image
I am using C++, hope some one out there can help me
( my previous thread which was closed )
https://stackoverflow.com/questions/5773638/converting-a-text-file-to-any-format-of-images-png-etc-c
thanx in advance
Help19
If you really really must store your data inside a PNG, it's better to use a 3rd party library like OpenCV to do the work for you. OpenCV will let you store your data and save it on the disk as PNG or any other format that it supports.
The code to do this would look something like this:
#include <cv.h>
#include <highgui.h>
IplImage* out_image = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, bits_pr_pixel);
char* buff = new char[width * height * bpp];
// then copy your data to this buff
out_image->imageData = buff;
if (!cvSaveImage("fake_picture.png", out_image))
{
std::cout << "ERROR: Failed cvSaveImage" << std::endl;
}
cvReleaseImage(&out_image);
The code above it's just to give you an idea on how to do what you need using OpenCV.
I think you're better served with a bi-dimensional bar code instead of converting your blob of data into a png image.
One of the codes that you could use is the QR code.
To do what you have in mind (storing data in an image), you'll need a lossless image format. PNG is a good choice for this. libpng is the official PNG encoding library. It's written in C, so you should be able to easily interface it with your C++ code. The homepage I linked you to contains links to both the source code so you can compile libpng into your project as well as a manual on how to use it. A few quick notes on using libpng:
It uses setjmp and longjmp for error handling. It's a little weird if you haven't worked with C's long jump functionality before, but the manual provides a few good examples.
It uses zlib for compression, so you'll also have to compile that into your project.

How to store wxImage into database, using C++?

I have some wxImages and I would like to store them into a BLOB (Binary Large OBject) field in a MySQL database.
There are no methods in wxImage nor wxBitmap for obtaining the binary data as an array of unsigned char so I can load into the database.
My current workaround is to write the image to a temporary file, then load the BLOB field directly from the file.
Is there a more efficient method to load and store a wxImage object into a MySQL BLOB field?
I am using MySql C++ connector 1.05, MS Visual Studio 2008, wxWidgets and C++.
wxWidgets doesn't provide any API to the data from wxBitmap (because it's platform-dependent) but wxImage uses a well-defined (and very simple) format which you can access using its GetData() method as mentioned above. Just notice that you may need to use GetAlpha() as well if your images have alpha channel.
However this is not how I'd do it because the data will be huge if you do it like this. While compressing it, as also suggested above, is possible, why bother doing it manually when wxImage already supports writing image in any of the standard image formats. Just create a wxMemoryOutputStream and pass it to SaveFile(). Then simply access the stream buffer directly using GetOutputStreamBuffer()->GetBufferStart() and related functions.
Unless I'm missing something, couldn't you use WxImage::GetData (http://docs.wxwidgets.org/2.8/wx_wximage.html#wximagegetdata) to get the data and then ::GetHeight and ::GetWidth to know the length of the data that pointer points to? The unsigned char * that is returned by WxImage::GetData looks like it should point to the RGB data that makes up the image.