Потоковое видео с камеры между двумя машинами Ubuntu - PullRequest
0 голосов
/ 18 июня 2020

Я пытаюсь передать через 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 не подходит для потоковой передачи изображений?

Спасибо за вашу помощь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...