I can't seem to find an example of the proper syntax/method for initializing an ImageMagick Magick++ object from an iostream stream_buffer in C++.
I'm trying to use the result from an aws sdk getObject which seems to return a stream buffer to push into ImageMagick to create thumbnails via lambda on demand.
example of the relevant code from the aws-sdk-cpp I'm using to retrieve the object:
auto get_object_outcome = s3_client.GetObject(object_request);
if (get_object_outcome.IsSuccess())
{
// Get an Aws::IOStream reference to the retrieved file
auto &retrieved_file = get_object_outcome.GetResultWithOwnership().GetBody();
// read the object's contents and write to a file
std::ofstream output_file(file_name, std::ios::binary);
output_file << retrieved_file.rdbuf();
return true;
}
else
{
auto error = get_object_outcome.GetError();
std::cout << "ERROR: " << error.GetExceptionName() << ": "
<< error.GetMessage() << std::endl;
return false;
}
Any help is appreciated - new to c++ so I'm not yet versed in converting more advanced data formats such as streams/blobs/buffers.
I try taking your retrieved_file, copy it into a std::vector, create an magick blob, create an image from the blob:
// create an empty buffer
std::vector<char> buffer;
// file your buffer with the retrieved file
std::copy(istream_iterator(retrieved_file), istream_iterator(), std::back_inserter(buffer));
// create a Magick++ blob with your data
Blob my_blob(buffer.data(), buffer.size());
// create a Magick++ image from your blob
Image image_from_blob(my_blob);
Related
Using libxml2. I can pretty-print the XML into a file by using xmlSaveFormatFileEnc(). But is there a way to do the same thing into a text string or stream?
I'd like to avoid writing the XML out to a file and reading it back in just to get the pretty-print version of the XML.
For the record, what I'm doing now is the following:
xmlInitParser();
xmlKeepBlanksDefault(0);
xmlLineNumbersDefault(1);
xmlThrDefIndentTreeOutput(1);
xmlThrDefTreeIndentString(" ");
std::string content = "....."; // do something here to get the XML
xmlDoc * doc = xmlParseDoc((xmlChar*)content.c_str());
xmlSaveFormatFileEnc("output.xml", doc, "utf-8", 1); // pretty print
Stolen from here:
xmlBufferPtr buf;
/* Create a new XML buffer, to which the XML document will be
* written */
buf = xmlBufferCreate();
if (buf == NULL) {
std::cerr << "testXmlwriterMemory: Error creating the xml buffer" << std::endl;
return;
}
/* Create a new XmlWriter for memory, with no compression.
* Remark: there is no compression for this kind of xmlTextWriter */
writer = xmlNewTextWriterMemory(buf, 0);
if (writer == NULL) {
std::cerr << "testXmlwriterMemory: Error creating the xml writer" << std::endl;
return;
}
And then, after you have written to the buffer:
std::cout << buf->content << std::endl
I am trying to create a music visualiser in C++ using SDL2 and FFTW3.
My aim is to load a .wav audio file and then simultaneously play the audio and perform a realtime Fast Fourier Transform using an SDL2 Callback function.
I want to get the frequency spectrum data so that I can implement the graphical visualiser at a later date.
I followed an SDL YouTube guide on loading the .wav and playing the audio using the callback function, but I don't understand how to perform the FFT on this data. I followed yet another guide on using FFTW and SDL with C to produce a similar effect but I'm still unsure how to actually implement it.
Uint8* sampData;
SDL_AudioSpec wavSpec;
Uint8* wavStart;
Uint32 wavLength;
SDL_AudioDeviceID aDevice;
struct AudioData {
Uint8* filePosition;
Uint32 fileLength;
};
void PlayAudioCallback(void* userData, Uint8* stream, int streamLength) {
AudioData* audio = (AudioData*)userData;
sampData = new Uint8;
if (audio->fileLength == 0) {
return;
}
Uint32 length = (Uint32)streamLength;
length = (length > audio->fileLength ? audio->fileLength : length);
SDL_memcpy(stream, audio->filePosition, length);
// HERE is where i'd like to implement the FFT on 'stream' data
// but i don't know how to implement this using FFTW
audio->filePosition += length;
audio->fileLength -= length;
}
int main() {
SDL_Init(SDL_INIT_AUDIO);
// Load .wav file
if (SDL_LoadWAV(FILE_PATH, &wavSpec, &wavStart, &wavLength) == NULL) {
cerr << "Couldnt load file: " << FILE_PATH << endl;
getchar();
}
cout << "Loaded " << FILE_PATH << endl;
AudioData audio;
audio.filePosition = wavStart;
audio.fileLength = wavLength;
wavSpec.callback = PlayAudioCallback;
wavSpec.userdata = &audio;
// Open audio playback endpoint
aDevice = SDL_OpenAudioDevice(NULL, 0, &wavSpec, NULL, SDL_AUDIO_ALLOW_ANY_CHANGE);
if (aDevice == 0) {
cerr << "Audio Device connection failed: " << SDL_GetError() << endl;
getchar();
}
// Play audio on playback endpoint
SDL_PauseAudioDevice(aDevice, 0);
// Do nothing while there's still data to be played
while (audio.fileLength > 0) {
SDL_Delay(100);
}
}
From previous experience I used NumPy to unpack .wav data into a NumPy array, before sending it the built-in NumPy-FFT function, but I'm clueless on what to do with the SDL stream data that I have here.
What you want is the short term FFT. You collect a buffer of samples from your stream and apply a window function to the samples before performing the FFT. You then collect another buffer, keeping some samples from the first buffer and appending new samples. Repeat until all the data has been processed.
Since your input data is real, the FFT is symmetric, hence you only want the first N/2+1 complex output bins. These represent frequencies from d.c. to Fs/2. Take their magnitudes and plot. Repeat for each FFT.
I have an image processing application that uses Qt and openCV.
for each frame, I should send the captured cv::Mat image object to the server to process it and get the results.
I should use the REST architecture for its low playload.
What is the tool that I should use to send cv::Mat to the server.
I am using POCO for portability.
I seek for the lightest solution to do that, I need a minimum speed of 10 frames processed by the server in a second.
I mean, is there a method to pass the C++ Object to the server without an explicit serialization?
EDIT
With the POCO library, you can take a look in this answer: HttpRequest PUT content in poco library. He is sending a file on a ifstream.
In this answer you can check how to convert a cv::Mat into a istream: OpenCV cv::Mat to std::ifstream for base64 encoding.
And finally, Thanks to polymorphism, the istream is implicity converted to a ifstream.
You can use the C++ Rest SDK. A code example of the PUT command.
Source of code
Library Github where you can find the full documentation.
#include <http_client.h>
#include <filestream.h>
#include <iostream>
#include <sstream>
using namespace web::http;
using namespace web::http::client;
// Upload a file to an HTTP server.
pplx::task<void> UploadFileToHttpServerAsync()
{
using concurrency::streams::file_stream;
using concurrency::streams::basic_istream;
// To run this example, you must have a file named myfile.txt in the current folder.
// Alternatively, you can use the following code to create a stream from a text string.
// std::string s("abcdefg");
// auto ss = concurrency::streams::stringstream::open_istream(s);
// Open stream to file.
return file_stream<unsigned char>::open_istream(L"myfile.txt").then([](pplx::task<basic_istream<unsigned char>> previousTask)
{
try
{
auto fileStream = previousTask.get();
// Make HTTP request with the file stream as the body.
http_client client(L"http://www.fourthcoffee.com");
return client.request(methods::PUT, L"myfile", fileStream).then([fileStream](pplx::task<http_response> previousTask)
{
fileStream.close();
std::wostringstream ss;
try
{
auto response = previousTask.get();
ss << L"Server returned returned status code " << response.status_code() << L"." << std::endl;
}
catch (const http_exception& e)
{
ss << e.what() << std::endl;
}
std::wcout << ss.str();
});
}
catch (const std::system_error& e)
{
std::wostringstream ss;
ss << e.what() << std::endl;
std::wcout << ss.str();
// Return an empty task.
return pplx::task_from_result();
}
});
/* Sample output:
The request must be resent
*/
}
I am trying to read parameters of Feature Detector (e.g.: SIFT) from an YAML file in OpenCV3.
I am trying to use the propose code in the Documentation. But it does not compile at all. So, I make it to compile, changing a little
#include "opencv2/opencv.hpp"
#include <opencv2/core/persistence.hpp>
#include "opencv2/xfeatures2d.hpp"
using namespace cv::xfeatures2d;
int main () {
cv::Ptr<cv::Feature2D> surf = SURF::create();
cv::FileStorage fs("../surf_params.yaml", cv::FileStorage::WRITE);
if( fs.isOpened() ) // if we have file with parameters, read them
{
std::cout << "reading parameters" << std::endl;
surf->read(fs["surf_params"]);
}
else // else modify the parameters and store them; user can later edit the file to use different parameters
{
std::cout << "writing parameters" << std::endl;
cv::Ptr<cv::xfeatures2d::SURF> aux_ptr;
aux_ptr = surf.dynamicCast<cv::xfeatures2d::SURF>();
aux_ptr->setNOctaves(3); // lower the contrast threshold, compared to the default value
{
cv::internal::WriteStructContext ws(fs, "surf_params", CV_NODE_MAP);
aux_ptr->write(fs);
}
}
fs.release();
// cv::Mat image = cv::imread("myimage.png", 0), descriptors;
// std::vector<cv::KeyPoint> keypoints;
// sift->detectAndCompute(image, cv::noArray(), keypoints, descriptors);
return 0;
}
But the the parameters are not read or wrote at all.
I also checked this Transition Guide, and in section "Algorithm interfaces" says that:
General algorithm usage pattern has changed: now it must be created on heap wrapped in smart pointer cv::Ptr. Version 2.4 allowed both stack and heap allocations, directly or via smart pointer.
get and set methods have been removed from the cv::Algorithm class along with CV_INIT_ALGORITHM macro. In 3.0 all properties have been converted to the pairs of getProperty/setProperty pure virtual methods. As a result it is not possible to create and use cv::Algorithm instance by name (using generic Algorithm::create(String) method), one should call corresponding factory method explicitly.
Maybe this means that it is not possible to read and write parameters from an XML/YAML files with read() and write() functions.
Can you give me some axample of how can I read parameters of Feature Detector algorithm from XML/YAML file in OpenCV3?
Thanks in advance!
If the specific algorithm overrides the methods cv::Algorithm::read and cv::Algorithm::write, then you can use then as described, for example, here.
However, cv::xfeatures2d::SURF doesn't overrides these methods, so you can't use this approach.
You can, however, store the properties you need to modify in a FileStorage, read and write them as usual, and modify the SURF object:
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/xfeatures2d/nonfree.hpp>
#include <iostream>
int main()
{
cv::Ptr<cv::Feature2D> surf = cv::xfeatures2d::SURF::create();
{
// Try to read from file
cv::FileStorage fs("surf_params.yaml", cv::FileStorage::READ);
if (fs.isOpened())
{
std::cout << "reading parameters" << std::endl;
// Read the parameters
int nOctaves = fs["nOctaves"];
surf.dynamicCast<cv::xfeatures2d::SURF>()->setNOctaves(nOctaves);
}
else
{
// Close the file in READ mode
fs.release();
// Open the file in WRITE mode
cv::FileStorage fs("surf_params.yaml", cv::FileStorage::WRITE);
std::cout << "writing parameters" << std::endl;
fs << "nOctaves" << 3;
// fs in WRITE mode automatically released
}
// fs in READ mode automatically released
}
}
You can make the surf object a pointer to cv::xfeatures2d::SURF to avoid casts:
cv::Ptr<cv::xfeatures2d::SURF> surf = ...
If you need to support different Features2D, you can store in the FileStorage also an identifier for the particular feature, such as:
fs << "Type" << "SURF";
and then conditionally read the options to restore its properties:
string type;
FileNode fn_type = fs.root();
type = fn_type["Type"];
if(type == "SURF") {
// Read SURF properties...
} else if(type == "SIFT") {
// Read SIFT properties...
}
I am new to this stuff, but I need to get the dc-coefficient from a jpeg using the jpeg library?
I was told as a hint that the corresponding function is in jdhuff.c, but I can't find it. I tried to find a decent article about the jpg library where I can get this, but no success so far.
So I hope you guys can help me a bit and point me to either some documentation or have a hint.
So, here is what I know:
A jpg picture consists of 8x8 Blocks. That are 64 Pixels. 63 of it are named AC and 1 is named DC. Thats the coefficient. The position is at array[0][0].
But how do I exactly read that with the jpg library? I am using C++.
edit:
This is what I have so far:
read_jpeg::read_jpeg( const std::string& filename )
{
FILE* fp = NULL; // File-Pointer
jpeg_decompress_struct cinfo; // jpeg decompression parameters
JSAMPARRAY buffer; // Output row-buffer
int row_stride = 0; // physical row width
my_error_mgr jerr; // Custom Error Manager
// Set Error Manager
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
// Handle longjump
if (setjmp(jerr.setjmp_buffer)) {
// JPEG has signaled an error. Clean up and throw an exception.
jpeg_destroy_decompress(&cinfo);
fclose(fp);
throw std::runtime_error("Error: jpeg has reported an error.");
}
// Open the file
if ( (fp = fopen(filename.c_str(), "rb")) == NULL )
{
std::stringstream ss;
ss << "Error: Cannot read '" << filename.c_str() << "' from the specified location!";
throw std::runtime_error(ss.str());
}
// Initialize jpeg decompression
jpeg_create_decompress(&cinfo);
// Show jpeg where to read the data
jpeg_stdio_src(&cinfo, fp);
// Read the header
jpeg_read_header(&cinfo, TRUE);
// Decompress the file
jpeg_start_decompress(&cinfo);
// JSAMPLEs per row in output buffer
row_stride = cinfo.output_width * cinfo.output_components;
// Make a one-row-high sample array
buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
// Read image using jpgs counter
while (cinfo.output_scanline < cinfo.output_height)
{
// Read the image
jpeg_read_scanlines(&cinfo, buffer, 1);
}
// Finish the decompress
jpeg_finish_decompress(&cinfo);
// Release memory
jpeg_destroy_decompress(&cinfo);
// Close the file
fclose(fp);
}
This is not possible using the standard API. With libjpeg API the closest you can get is raw pixel data of Y/Cb/Cr channels.
To get coefficients' data you'd need to hack the decode_mcu function (or its callers) to save the data decoded there.