C++
接收端
#include <iostream>
#include <opencv.hpp>
#include <WinSock2.h>
#pragma comment(lib,"WS2_32.lib")
using namespace std;
using namespace cv;
int main()
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("init windows socket error: errno %d\n",WSAGetLastError());
return -1;
}//创建初始化句柄
SOCKET sockServe;
if ((sockServe = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) //创建socket句柄,采用UDP协议
{
printf("create socket error: errno %d\n", WSAGetLastError());
return -1;
}
sockaddr_in servaddr;
servaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
servaddr.sin_family = AF_INET; //设置通信方式
servaddr.sin_port = htons(8554); //设置端口号
if (::bind(sockServe, (const sockaddr*)&servaddr, sizeof(servaddr)) == SOCKET_ERROR)
{
printf("bind socket with IP error: errno %d\n", WSAGetLastError());
return -1;
}//绑定套接字
listen(sockServe, 3);
Mat image;
int MAX_DGRAM = 65536;
char buf[65536];
while (true)
{
std::vector<uchar> decode;
int count;
do
{
int nBytes = recv(sockServe, buf, sizeof(buf), 0);//接受缓存
count = buf[0];
for (int i = 1; i < nBytes; i++)
{
decode.push_back(buf[i]);
}
cout << count << endl;
} while (count > 1);
image = imdecode(decode, cv::ImreadModes::IMREAD_COLOR);//图像解码
cout<<image.size()<<endl;
//在UDP传输的过程中,可能回发生丢包,因此需要对接受到的影像进行判断
if (image.empty())
{
continue;
}
imshow("serve image", image);
cv::waitKey(1);
}
closesocket(sockServe);
WSACleanup();
return 0;
}
发送端
#include <iostream>
#include <opencv.hpp>
#include <WinSock2.h>
#pragma comment(lib,"WS2_32.lib")
using namespace std;
using namespace cv;
#define MAX_DGRAM 65535
int main()
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
//errno 是error.h中定义的宏,表示的是程序运行是发生错误的错误代码
//strerror定义在string.h中,用于打印错误代码对应的错误描述
printf("init windows socket error:errno %d\n",WSAGetLastError());
return -1;
}//创建初始化句柄
SOCKET clientSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (clientSock == INVALID_SOCKET)
{
printf("create client socket error:errno %d\n",WSAGetLastError());
return -1;
}
//定义服务端的IP地址,向服务端发送请求
sockaddr_in serveaddr;
memset(&serveaddr, 0, sizeof(serveaddr));
serveaddr.sin_family = AF_INET;
serveaddr.sin_port = htons(8554);
serveaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
VideoCapture vCapture(0);
while (true)
{
if (!vCapture.isOpened())
{
break;
}
Mat image;
bool flag = vCapture.read(image);
if (!flag)
{
break;
}
vector<uchar> imageBuf;
int bufSize;
imencode(".jpg", image, imageBuf);
bufSize = imageBuf.size();
char imageBlockBuf[65536];
int count = ceil(1.0*bufSize / MAX_DGRAM);
int start_index = 0, end_index;
while (count)
{
end_index = start_index + MAX_DGRAM;
if (end_index > bufSize)
{
end_index = bufSize;
}
imageBlockBuf[0] = count;
int pos = 1;
for (int i = start_index; i < end_index; i++)
{
imageBlockBuf[pos] = imageBuf[i];
pos++;
}
sendto(clientSock, imageBlockBuf, end_index-start_index+1, 0, (const sockaddr *)&serveaddr, sizeof(serveaddr));
count--;
start_index = end_index;
}
cv::imshow("client", image);
cv::waitKey(1);
}
closesocket(clientSock);
WSACleanup();
return 0;
}
python
接收端
#!/usr/bin/env python
from __future__ import division
import cv2
import numpy as np
import socket
import struct
MAX_DGRAM = 2**16
def main():
""" Getting image udp frame &
concate before decode and output image """
# Set up socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 8554))
dat = b''
while True:
seg, addr = s.recvfrom(MAX_DGRAM)
if struct.unpack("B", seg[0:1])[0] > 1:
dat += seg[1:]
else:
dat += seg[1:]
print(np.fromstring(dat, dtype=np.uint8))
img = cv2.imdecode(np.fromstring(dat, dtype=np.uint8), 1)
print(img)
cv2.imshow('frame', img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
dat = b''
cv2.destroyAllWindows()
s.close()
if __name__ == "__main__":
main()
发送端
#!/usr/bin/env python
from __future__ import division
import cv2
import numpy as np
import socket
import struct
import math
class FrameSegment(object):
"""
Object to break down image frame segment
if the size of image exceed maximum datagram size
"""
MAX_DGRAM = 2**16
MAX_IMAGE_DGRAM = MAX_DGRAM - 64 # extract 64 bytes in case UDP frame overflown
def __init__(self, sock:socket.socket, port, addr="127.0.0.1"):
self.s = sock
self.port = port
self.addr = addr
def udp_frame(self, img):
"""
Compress image and Break down
into data segments
"""
compress_img = cv2.imencode('.jpg', img)[1]
dat = compress_img.tostring()
size = len(dat)
print(size)
count = math.ceil(size/(self.MAX_IMAGE_DGRAM))
array_pos_start = 0
while count:
array_pos_end = min(size, array_pos_start + self.MAX_IMAGE_DGRAM)
self.s.sendto(struct.pack("B", count) +
dat[array_pos_start:array_pos_end],
(self.addr, self.port)
)
array_pos_start = array_pos_end
count -= 1
def main():
""" Top level main function """
# Set up UDP socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
port = 8554
fs = FrameSegment(s, port)
cap = cv2.VideoCapture(0)
while (cap.isOpened()):
_, frame = cap.read()
fs.udp_frame(frame)
cv2.imshow("client",frame)
cv2.waitKey(1)
cap.release()
cv2.destroyAllWindows()
s.close()
if __name__ == "__main__":
main()
运行
两种不同语言的接收端和服务端可以混合使用