Cannot decode server-sent uchar vector on client side: Empty Mat results.
Hello, thank-you in advance for any help that may be provided here: I am trying to send a Mat image from a server to a client over TCP-ip with winsock (between two different PC's). Like many others in these forums I am also new to socket programming. I have followed this very good thread "https://answers.opencv.org/question/1..." which I have basically adopted for my own solution. Thank-you therefore to the contributors (pwk3, berak & opalmirror).
I have "successfully" been able to send a uchar vector, (converted from cv::Mat via imencode(..)) which appears to be exactly the same size when received on the client-side in comparison to the server-side prior to sending. Unfortunately however when I try to decode it on the client side it results in an empty matrix. According to the docs: "If the buffer is too short or contains invalid data, the function returns an empty matrix ( Mat::data==NULL )." Therefore I am assuming that although the exact number of bytes were sent... there is still some corruption somewhere. If I decode the encoded buffer on the server side before transmission the original Mat is directly recoverable with the same code. Hence the issue has to occur in the transmission between PC's somehow.
I have attached code replicating the problem whereby the server sends one image and the receiver receives the full buffer but fails to decode:
If someone could please assist in perhaps explaining why I am able to decode on the server side without obtaining an empty Mat but not on the client that would be much appreciated. I feel the data must somehow be corrupted during transmission (even though it looks as though all data was received). Any tips would be much appreciated.
Thank-you in advance.
// ~~~~~~~~~~~~~~~~~~~~ Code Server: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <ws2tcpip.h>
#include <string>
#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/core/utils/trace.hpp>
using namespace cv;
int main(int argc, char* argv[])
{
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsInit = WSAStartup(ver, &data);
// 2. Create listening socket
SOCKET listener = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in hints;
hints.sin_family = AF_INET;
hints.sin_port = htons(54000);
WSADATA wsa_Data;
int wsa_ReturnCode = WSAStartup(0x101, &wsa_Data);
// 3. Get the local ipAddress
char szHostName[255];
gethostname(szHostName, 255);
struct hostent* host_entry;
host_entry = gethostbyname(szHostName);
char* ipAddress;
ipAddress = inet_ntoa(*(struct in_addr*)*host_entry->h_addr_list);
inet_pton(AF_INET, std::string(ipAddress).c_str(), &hints.sin_addr);
// 4. Bind socket
int bind_ok = bind(listener, (sockaddr*)&hints, sizeof(hints));
if (bind_ok != SOCKET_ERROR) {
if (listen(listener, SOMAXCONN) == SOCKET_ERROR)
return 0;
}
// 5. Accept client
SOCKET client = accept(listener, NULL, NULL); // waits for connection
std::cout << "Established connection from " << client << std::endl;
if (client != INVALID_SOCKET) {
closesocket(listener);
WSACleanup();
}
// 6. Encode frame:
cv::Mat frame = cv::imread("../../data/img_sample.jpg");
std::vector<uchar> buf(50000);
cv::imencode(".jpg", frame, buf);
// Decoding the buffer here results in original image without issues
// cv::Mat frame2 = cv::imdecode(cv::Mat(buf), 1);
size_t ...
please show your code, but NO SCREENSHOTS of code or msgs here, please. if noone can try it out or google it -- noone will help you.
please edityour question, and add resp. code AS TEXT, thank you.
Apologies berak, that was a bit silly of me. Thank-you very much for your response: I have now updated my question.
std::vector <char> buffer_uchar;
can you try to really use uchar, not char ? (at least as input to imdecode)also:
sizeof(size_t) may not be sizeof(int)
Ok that was all the help I needed. The sizeof(size_t) was the issue! It seems like an obvious error now - apologies for that.. Thank-you very much for your quick and correct response. I would like to upvote your answer but need an additional number of points first as a new member. Cheers :)
@greggaz - dare to answer yourown question !
haha as a new user I need to wait two days after question originally posted... therefore another 4 hours. Will update :)