RaspbianWindows openCV videostream之间的套接字

2024-06-18 11:22:15 发布

您现在位置:Python中文网/ 问答频道 /正文

这是我第一次问这个问题,但我已经找了很长时间的解决方案,我一直找不到它,所以我会努力解决这个问题,如果有更多的人有同样的问题,帮助那些与这个线程。希望它不是复制品!你知道吗

<>我在Wiels7,C++,Visual Studio 2015有一个服务器,在那里我有一些运行在OpenCV中的例程。我将其中一些任务从我的计算机中转移到一个远程的Raspberry pi3,所以我用python3编程了一个客户端,它也使用套接字。你知道吗

服务器(C++)和客户端(Python)在发送诸如“Hello World!”这样的字符串时都是正常工作的。还有那些东西。当我开始发送二进制数据时,问题来了。你知道吗

我在openCV(客户端python端)中有一个图像,我使用了imencode函数:

data = cv2.imencode(".jpg", image, [int(cv2.IMWRITE_JPEG_QUALITY), 90])[1].tostring()

然后我有一个缓冲区,在那里存储要发送的信息,所以我将数据添加到缓冲区:

buffer.append(data)

然后,填充缓冲区后,我通过套接字客户端发送第一个图像:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect("some_address and some port")
sock.send(data)
sock.close()

同时,在服务器端(C++)中,我初始化了Windows套接字,解决了地址,创建了一个侦听套接字,将侦听套接字连接到服务器地址,并等待客户端连接到侦听套接字。当客户端连接时,侦听套接字关闭,我调用开始接收方法:

do {
    iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
    if (iResult > 0) {
        totalBytes += iResult;
        std::cout << recvbuf << std::endl;
        ss << recvbuf;

        std::cout << ss.str() << std::endl;
        std::cout << "Bytes received: " << iResult << std::endl;

        // Echo the buffer back to the sender
        iSendResult = send(ClientSocket, recvbuf, iResult, 0);
        if (iSendResult == SOCKET_ERROR) {
            std::cout << "send failed with error: " << WSAGetLastError() << std::endl;
            closesocket(ClientSocket);
            WSACleanup();
            break;
        }
        std::cout << "Bytes sent: " << iSendResult << std::endl;
    }
    else if (iResult == 0) {
        std::cout << "Connection closing..." << std::endl;
    } else {
        std::cout << "recv failed with error: " << WSAGetLastError() << std::endl;
        closesocket(ClientSocket);
        WSACleanup();
        break;
    }
} while (iResult > 0);
addData(ss.str());

然后,addData将接收到的信息压回队列缓冲区(在互斥区域内),转换为uint8:

std::vector<uint8_t> v(data.begin(), data.end());
lck.lock();
buffer.push(v);
lck.unlock();

从我程序的另一部分,我正在读取(以及在互斥区域内)队列中最古老的元素

std::vector<uint8_t> & ImageServer::getNextImage()
{
    lck.lock();
    if (buffer.size() > 0)
    {
        frameJPG = buffer.front();
        buffer.pop();
    }

    lck.unlock();
    return frameJPG;
}

我试着用openCV函数再次解码:

try {
    vec = is->getNextImage();
    img = cv::imdecode(vec, CV_LOAD_IMAGE_UNCHANGED);

    if (img.data == NULL)
        std::cout << "Image in buffer couldn't be properly decoded" << std::endl;
    else
        std::cout << "IMAGE RECOVERED!" << std::endl;
} catch (...) {
    std::cout << "AN UNKNOWN ERROR OCURRED" << std::endl;
}

它总是进入图像数据==空。这意味着没有足够的数据(不是这样),或者数据不能正确格式化。为什么?当我把它存储到一个stringstream中作为第一个缓冲区来收集整个数据流时,我把事情搞砸了?它被分成1024个字节的包。。。你知道吗

我查过了:

  1. 服务器中接收到的数据的大小等于客户端中的数据大小。你知道吗
  2. b“你好,世界!”正在正确发送和接收字符串。你知道吗
  3. Raspbian和Windows7都是LittleEndian
  4. 两个OpenCV安装都是openCV3.x

在对不同的铸件进行了1000次不同的测试之后,我陷入了同一个困境:一个我无法解析的二进制流。OpenCV在Windows和Python中的行为是否不同,所以它不能在C++中解码在Python中编码的内容吗?套接字是否接收未排序的信息?插座是否添加了一些我必须以某种方式修剪的标题?它是由操作系统体系结构(x86与x64)引起的吗?你知道吗

事先非常感谢。你知道吗

如果你需要更多的代码,我也可以张贴,但我想保持它干净!你知道吗

谨致问候, 迈耶


Tags: 数据服务器客户端dataifbuffersocket缓冲区
2条回答

是的!厄蒂布,就是这样。上周五我对此表示怀疑,你是对的。今天早上我修改了它,它工作得很顺利,除了add和get data方法之外,没有对代码进行任何其他修改!(以适应新的数据结构)。你知道吗

这是我在第一次测试中做的:

std::vector<uint8_t> v;
// Receive until the peer shuts down the connection
do {
    iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
    if (iResult > 0) {
        totalBytes += iResult;
        for (auto i = 0; i < iResult; ++i)
            v.push_back(recvbuf[i]);
    //some more lines unreleated to the answer

有没有更有效的方法来填充向量v? 非常感谢您在这方面的帮助!你知道吗

附言:很抱歉,我不能推翻你的回答,因为我没有这样做的名声:-(

我认为您的字节会被ss << recvbuf;剪切,因为<<recvbuf视为以null结尾的字符串。相反,它应该被视为包含iResult字节的缓冲区。这意味着它不是以null结尾的,它的最后一个字节可能是任何字符,并且中间可能有null值。你知道吗

我建议放弃ss,而是直接从recvbuf中接收的片段构建std::vector<uint8_t>。你知道吗

可以将recvbuf的所有内容插入到向量v的末尾,如下所示:

v.insert(v.end(), recvbuf, recvbuf + iResult);

相关问题 更多 >