python - Raspbian-Windows openCV 视频流之间的套接字

标签 python c++ sockets opencv

这是我第一次在这里提问,但我一直在寻找解决方案很长时间,但一直找不到,所以我会尝试解决这个问题,如果更多人遇到同样的问题,请帮助那些有这个线程。希望它没有被完全复制!

我在 Windows7、C++、Visual Studio 2015 中有一个服务器,其中我有一些在 openCV 中运行的例程。我正在将其中一些任务从我的计算机转移到远程 Raspberry Pi 3,因此我在 Python 3 中编写了一个也使用套接字的客户端。

在发送诸如“Hello World!”之类的字符串时,服务器 (C++) 和客户端 (Python) 都可以正常工作。和那些东西。当我开始发送二进制数据时,问题就来了。

我在 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;
}

它总是进入 img.data == NULL。这意味着没有足够的数据(并非如此)或数据无法正确格式化。为什么?将它作为第一个缓冲区存储到 stringstream 中以收集整个数据流时,我把事情搞砸了吗?它被分成1024字节的包...

我检查过:

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

在使用不同的转换进行 1000 次不同的测试后,我卡在了同一个点:一个我无法解析的二进制流。 OpenCV 在 Windows 和 Python 中的行为方式是否不同,因此它无法在 C++ 中解码在 Python 中编码的内容?套接字是否接收未分类的信息? socket 是否添加了一些我必须以某种方式修剪的标题?是否由操作系统架构(x86 与 x64)引起?

非常感谢您。

如果您需要更多代码,我也可以发布,但我希望保持代码整洁!

问候, 迈杰

最佳答案

我认为您的字节被 ss << recvbuf; 削减了自 <<对待recvbuf作为空终止字符串。相反,它应该被视为包含 iResult 的缓冲区。字节。这意味着它不是以 null 结尾的,它的最后一个字节可以是任何内容,并且中间可能有 null 值。

我建议放弃 ss而是构建一个 std::vector<uint8_t>直接来自 recvbuf 中收到的作品.

您可以插入 recvbuf 的所有内容到 vector 的结尾 v像那样:

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

关于python - Raspbian-Windows openCV 视频流之间的套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51990390/

相关文章:

python - 根据校验和计算出的 LRC 值不正确

c++ - Qt QString toInt() 失败

python - 套接字:使用一台机器/网卡在python中模拟多个客户端

python - 联合异步迭代器会发生什么?

python - 带有 isin 的 Pandas 函数

c++ - 为什么空 while 循环使用更多的 cpu?

c - 使用带套接字的 C 中的 I/O 从服务器接收响应

PHP Ratchet 无法从其他设备连接

python - Numpy:nanargmin 如果行包含所有 NaN,则选择索引 0

c++ - C++ 中的 C99 样式可变长度数组函数签名