Ask Your Question
1

Cannot decode server-sent uchar vector on client side: Empty Mat results.

asked 2020-09-24 18:49:14 -0600

greggaz gravatar image

updated 2020-09-26 06:02:35 -0600

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 ...
(more)
edit retag flag offensive close merge delete

Comments

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.

berak gravatar imageberak ( 2020-09-25 01:11:16 -0600 )edit
1

Apologies berak, that was a bit silly of me. Thank-you very much for your response: I have now updated my question.

greggaz gravatar imagegreggaz ( 2020-09-26 06:03:20 -0600 )edit

std::vector <char> buffer_uchar; can you try to really use uchar, not char ? (at least as input to imdecode)

also:

size_t buffer_size = 0;
while (buffer_size == 0) {
    recv(clientSocket, (char *)(&buffer_size), sizeof(int), 0);
}

sizeof(size_t) may not be sizeof(int)

berak gravatar imageberak ( 2020-09-26 06:20:40 -0600 )edit

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 gravatar imagegreggaz ( 2020-09-26 13:26:07 -0600 )edit

@greggaz - dare to answer yourown question !

berak gravatar imageberak ( 2020-09-26 14:19:22 -0600 )edit

haha as a new user I need to wait two days after question originally posted... therefore another 4 hours. Will update :)

greggaz gravatar imagegreggaz ( 2020-09-26 14:43:08 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
3

answered 2020-09-26 19:26:00 -0600

greggaz gravatar image

So it was indeed an embarrasing overlooked syntax error on my behalf. As pointed out by berak in the comments I had sizeof(int) instead of sizeof(size_t) where size_t would have reflected the correct variable type. Cheers

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2020-09-24 18:49:14 -0600

Seen: 332 times

Last updated: Sep 26 '20