python - Raspbian-Windows 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 socket,解析了地址,创建了一个监听socket,将监听socket链接到服务器地址,等待客户端连接监听socket。当客户端连接时,监听套接字关闭,我调用开始接收方法:
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。这意味着没有足够的数据(不是这种情况)或数据无法正确格式化。为什么?将其存储到字符串流中作为第一个缓冲区以收集整个数据流时,我搞砸了?它被分成1024字节的包......
我检查过:
- 服务器接收到的数据大小等于客户端的数据大小。
- b“你好,世界!” 字符串正在正确发送和接收。
- Raspbian 和 Windows 7 都是小端
- 两个 OpenCV 安装都是 openCV3.x
在使用不同的铸件进行 1000 次不同的测试后,我被困在同一点:我无法解析的二进制流。OpenCV 在 Windows 和 Python 中的行为方式是否不同,因此它无法在 C++ 中解码 Python 中编码的内容?套接字是否接收未排序的信息?插座是否添加了一些我必须以某种方式修剪的标题?它是由操作系统架构(x86 vs x64)引起的吗?
非常感谢你。
如果您需要更多代码,我也可以发布,但我想保持干净!
问候, 梅杰
解决方案
我认为您的字节被削减了,ss << recvbuf;
因为<<
将其recvbuf
视为以空字符结尾的字符串。相反,它应该被视为包含iResult
字节的缓冲区。这意味着它不是以空值结尾的,它的最后一个字节可以是任何东西,并且中间可能有空值。
我建议放弃它ss
,而是std::vector<uint8_t>
直接从recvbuf
.
您可以像这样将所有内容插入recvbuf
到向量的末尾v
:
v.insert(v.end(), recvbuf, recvbuf + iResult);
推荐阅读
- python - 在元组的元组列表中通过内部元组查找元素
- visual-studio-code - 向上/向下移动打开编辑器的 VSCode 快捷方式(不是组,而是打开编辑器)
- python - Python-检查值在无限范围内
- python - 通过 for 循环后计数器变量没有改变
- javascript - 检测数组元素中的组合
- drake - Drake 中的差动驱动机器人仿真
- objective-c - 实施 FCM 时,没有为应用程序错误找到有效的“aps-environment”权利字符串
- python - 在具有多个键的字典内循环
- snowflake-cloud-data-platform - 如何找到运行最多查询的用户/角色
- powershell - 优先启动进程