Send image from OpenCV 3 to Cognitive Face API using C ++ REST SDK
I want to use Microsoft Face API from a C ++ application. Cpprest sdk allows me to send image url or image binary data. The problem is my image is not a file on disk, but a cv :: Mat in memory. I'm trying to serialize it using a string stream, but the request method is complaining because it only accepts some strings and an istream.
The following code is fine when opening an image from a file:
file_stream<unsigned char>::open_istream(filename)
.then([=](pplx::task<basic_istream<unsigned char>> previousTask)
{
try
{
auto fileStream = previousTask.get();
auto client = http_client{U("https://api.projectoxford.ai/face/v0/detections")};
auto query = uri_builder()
.append_query(U("analyzesFaceLandmarks"), analyzesFaceLandmarks ? "true" : "false")
.append_query(U("analyzesAge"), analyzesAge ? "true" : "false")
.append_query(U("analyzesGender"), analyzesGender ? "true" : "false")
.append_query(U("analyzesHeadPose"), analyzesHeadPose ? "true" : "false")
.append_query(U("subscription-key"), subscriptionKey)
.to_string();
client
.request(methods::POST, query, fileStream)
...
}
}
Here file_stream is used to open a file. I've tried serializing my Mat like this:
// img is the cv::Mat
std::vector<uchar> buff;
cv::imencode(".jpg", img, buff);
std::stringstream ssbuff;
copy(buff.begin(), buff.end(), std::ostream_iterator<unsigned char>(ssbuff,""));
This serialization works the way I can decode if after and rebuild the image.
¿How can I send opencv Mat image to server via client?
source to share
This question here (the best way to load uint8_t array into azure blob storage with wastorage in C ++ ) will lead me to the final answer.
The request method for the client asks for a concurrency :: streams :: istream object when submitting raw data (see docs here: https://microsoft.github.io/cpprestsdk/classweb_1_1http_1_1client_1_1http__client.html#a5195fd9b36b8807456 a string containing byc5195fd9b36b8807456 string3) should be passed to a bytestream object provided by the SDK and open it with an istream object (also provided by the SDK).
concurrency::streams::bytestream byteStream =
concurrency::streams::bytestream();
concurrency::streams::istream inputStream =
byteStream.open_istream(ssbuff.str());
auto fileStream = inputStream;
// Build uri and so on ...
client.request(methods::POST, query, fileStream)
// async processing ...
The request type is not needed to be explicit as it defaults to "application / octet-stream" according to the docs.
source to share