Я пытаюсь передать через TCP (почти в реальном времени) изображения, снятые с моей камеры, подключенной к моему P C, на Raspberry Pi 4. На P C (клиент) мой код написан на Python, тогда как на Raspberry (сервере) код написан на C ++.
Здесь 2 кода (клиент / сервер)
#!/usr/bin/python
# client.py
import socket
import cv2
import numpy as np
from threading import Thread
TCP_IP = '192.168.1.24'
#TCP_IP = 'localhost'
TCP_PORT = 5002
queue = []
sock = socket.socket()
sock.connect((TCP_IP, TCP_PORT))
BATCH_SIZE = 1
encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),25]
capture = cv2.VideoCapture(1)
class queue_thread(Thread):
def __init__(self):
Thread.__init__(self)
def run(self):
print("Queue thread..")
while(1):
if(len(queue)>20): continue
data=np.array([[]],np.uint8).transpose()
for i in range(BATCH_SIZE):
ret, frame = capture.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frame = cv2.resize(frame, (320,240))
result, imgencode = cv2.imencode('.jpg', frame, encode_param)
data = np.vstack([data,np.array(imgencode)])
stringData = data.tostring()
queue.append(stringData)
queuet = queue_thread()
queuet.start()
while(1):
if(len(queue)==0): continue
sock.send((str(len(queue[0])).ljust(16)).encode());
print(len(queue[0]))
sock.sendall(queue[0]);
queue.pop(0)
sock.close()
И для серверной части:
# server.cpp
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <opencv2/videoio/videoio_c.h>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#define TMAX 2000000
#define JPEG_PORT 5002
//#define JPEG_IP "localhost"
#define JPEG_IP "192.168.1.24"
#define SA struct sockaddr
using namespace cv;
using namespace std;
int command_sockfd;
std::vector<Mat> images;
Mat decodedImage;
void *Queue_Thread(void *vargp)
{
printf("Inizio\n");
while (1)
{
uchar buff[TMAX];
uchar buff2[TMAX];
int n;
int error = 0;
int sockfd, connfd;
socklen_t len;
int retval;
int enable = 1;
struct sockaddr_in servaddr, cli;
// socket create and verification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
printf("socket creation failed...\r\n");
}
else
{
printf("Socket successfully created..\r\n");
}
printf("set opt\n");
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
perror("setsockopt(SO_REUSEADDR) failed");
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int)) < 0)
perror("setsockopt(SO_REUSEPORT) failed");
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(JPEG_PORT);
// Binding newly created socket to given IP and verification
if((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0)
{
printf("socket bind failed...\r\n");
sleep(2);
close(sockfd);
continue;
}
else
{
printf("Socket successfully binded ok..\r\n");
}
// Now server is ready to listen and verification
if((listen(sockfd, 5)) != 0) {
printf("Listen failed...\r\n");
}
else
{
printf("Server listening..\r\n");
}
len = sizeof(cli);
// Accept the data packet from client and verification
connfd = accept(sockfd, (SA*)&cli, &len);
if (connfd < 0)
{
printf("server acccept failed...\r\n");
}
else
{
printf("server acccept the client...\r\n");
}
while (1) {
bzero(buff, TMAX);
bzero(buff2, TMAX);
read(connfd, buff, 16);
int bytesRead = 0;
int result;
int size = atoi((char*)buff);
//cout << size << endl;
if(size==0) continue;
bzero(buff, TMAX);
while (bytesRead < size)
{
result = read(connfd, buff + bytesRead, size - bytesRead);
bytesRead += result;
}
//read(connfd, buff, size);
read(sockfd, buff2, sizeof(buff2));
if (strlen((char*)buff2) >= 0)
{
Mat rawData( 1, size, CV_8UC1, (void*)buff );
if(255!=rawData.at<uint8_t>(0,size-2) || 217!=rawData.at<uint8_t>(0,size-1))
{
cout << "Not JPEG: " << strlen((char*)buff) << endl;
continue;
}
decodedImage = imdecode( rawData,1);
if(decodedImage.size().height<=0 || decodedImage.size().width<=0)
{
cout << decodedImage.size().height << "x" << decodedImage.size().width << endl;
continue;
}
images.push_back(decodedImage);
}
else
{
close(sockfd);
printf("Connection lost, trying to reconnect...\n");
break;
}
}
}
}
int main()
{
pthread_t queue_thread_t;
pthread_create(&queue_thread_t, NULL, Queue_Thread, NULL);
while(1)
{
if(images.size()<10) continue;
else
{
cout << "Queue size: " << images.size() << endl;
imshow("SERVER", images[0]);
waitKey(1);
images.erase(images.begin() + 0);
}
}
return 0;
}
Он работает довольно хорошо, но немного медленнее, и много раз я получаю поврежденные данные на стороне сервера.
Есть способ повысить скорость? Сервер и клиент находятся в одной сети, и я подумал, что этого достаточно для хорошей скорости. Может TCP не подходит для потоковой передачи изображений?
Спасибо за вашу помощь.